2020-05-18 12:06:36 +02:00
package handler
import (
2022-03-28 10:05:09 +02:00
"context"
2025-05-28 23:54:18 +02:00
"errors"
2025-04-29 17:29:16 +02:00
"fmt"
2020-07-28 09:42:21 +02:00
"time"
2025-05-28 23:54:18 +02:00
"github.com/jackc/pgx/v5/pgconn"
2025-04-29 17:29:16 +02:00
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/api/authz"
2022-04-27 01:01:45 +02:00
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/view"
2023-10-19 12:19:10 +02:00
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/eventstore"
2024-01-25 17:28:20 +01:00
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
2023-10-19 12:19:10 +02:00
handler2 "github.com/zitadel/zitadel/internal/eventstore/handler/v2"
2024-09-03 15:19:00 +02:00
"github.com/zitadel/zitadel/internal/id"
2022-04-27 01:01:45 +02:00
query2 "github.com/zitadel/zitadel/internal/query"
2020-05-18 12:06:36 +02:00
)
type Config struct {
2023-10-19 12:19:10 +02:00
Client * database . DB
Eventstore * eventstore . Eventstore
2020-05-18 12:06:36 +02:00
2023-10-19 12:19:10 +02:00
BulkLimit uint64
FailureCountUntilSkip uint64
TransactionDuration time . Duration
Handlers map [ string ] * ConfigOverwrites
2024-12-06 12:32:53 +01:00
ActiveInstancer interface {
ActiveInstances ( ) [ ] string
}
2020-05-18 12:06:36 +02:00
}
2023-10-19 12:19:10 +02:00
type ConfigOverwrites struct {
MinimumCycleDuration time . Duration
2020-05-18 12:06:36 +02:00
}
2020-07-28 09:42:21 +02:00
2024-01-25 17:28:20 +01:00
var projections [ ] * handler . Handler
2023-10-19 12:19:10 +02:00
func Register ( ctx context . Context , configs Config , view * view . View , queries * query2 . Queries ) {
2024-12-06 12:32:53 +01:00
// make sure the slice does not contain old values
projections = nil
2024-01-25 17:28:20 +01:00
projections = append ( projections , newUser ( ctx ,
2023-10-19 12:19:10 +02:00
configs . overwrite ( "User" ) ,
view ,
queries ,
2024-01-25 17:28:20 +01:00
) )
2020-07-28 09:42:21 +02:00
2024-01-25 17:28:20 +01:00
projections = append ( projections , newUserSession ( ctx ,
2023-10-19 12:19:10 +02:00
configs . overwrite ( "UserSession" ) ,
view ,
queries ,
2024-09-03 15:19:00 +02:00
id . SonyFlakeGenerator ( ) ,
2024-01-25 17:28:20 +01:00
) )
2020-12-22 12:27:55 +01:00
2024-01-25 17:28:20 +01:00
projections = append ( projections , newToken ( ctx ,
2023-10-19 12:19:10 +02:00
configs . overwrite ( "Token" ) ,
view ,
2024-01-25 17:28:20 +01:00
) )
2022-03-28 10:05:09 +02:00
2024-01-25 17:28:20 +01:00
projections = append ( projections , newRefreshToken ( ctx ,
2023-10-19 12:19:10 +02:00
configs . overwrite ( "RefreshToken" ) ,
view ,
2024-01-25 17:28:20 +01:00
) )
}
func Start ( ctx context . Context ) {
for _ , projection := range projections {
projection . Start ( ctx )
}
}
func Projections ( ) [ ] * handler2 . Handler {
return projections
2022-03-28 10:05:09 +02:00
}
2022-07-22 12:08:39 +02:00
2024-05-30 11:35:30 +02:00
func ProjectInstance ( ctx context . Context ) error {
2025-04-29 17:29:16 +02:00
for i , projection := range projections {
logging . WithFields ( "name" , projection . ProjectionName ( ) , "instance" , authz . GetInstance ( ctx ) . InstanceID ( ) , "index" , fmt . Sprintf ( "%d/%d" , i , len ( projections ) ) ) . Info ( "starting auth projection" )
2025-05-28 23:54:18 +02:00
for {
_ , err := projection . Trigger ( ctx )
if err == nil {
break
}
var pgErr * pgconn . PgError
errors . As ( err , & pgErr )
if pgErr . Code != database . PgUniqueConstraintErrorCode {
return err
}
logging . WithFields ( "name" , projection . ProjectionName ( ) , "instance" , authz . GetInstance ( ctx ) . InstanceID ( ) ) . WithError ( err ) . Debug ( "auth projection failed because of unique constraint, retrying" )
2024-05-30 11:35:30 +02:00
}
2025-04-29 17:29:16 +02:00
logging . WithFields ( "name" , projection . ProjectionName ( ) , "instance" , authz . GetInstance ( ctx ) . InstanceID ( ) , "index" , fmt . Sprintf ( "%d/%d" , i , len ( projections ) ) ) . Info ( "auth projection done" )
2024-05-30 11:35:30 +02:00
}
return nil
}
2023-10-19 12:19:10 +02:00
func ( config Config ) overwrite ( viewModel string ) handler2 . Config {
c := handler2 . Config {
2024-12-06 12:32:53 +01:00
Client : config . Client ,
Eventstore : config . Eventstore ,
BulkLimit : uint16 ( config . BulkLimit ) ,
RequeueEvery : 3 * time . Minute ,
MaxFailureCount : uint8 ( config . FailureCountUntilSkip ) ,
TransactionDuration : config . TransactionDuration ,
ActiveInstancer : config . ActiveInstancer ,
2023-10-19 12:19:10 +02:00
}
overwrite , ok := config . Handlers [ viewModel ]
if ! ok {
return c
}
if overwrite . MinimumCycleDuration > 0 {
c . RequeueEvery = overwrite . MinimumCycleDuration
2022-07-22 12:08:39 +02:00
}
2023-10-19 12:19:10 +02:00
return c
2022-07-22 12:08:39 +02:00
}