diff --git a/cmd/zitadel/caos_local.sh b/cmd/zitadel/caos_local.sh index 76ec5ae792..817761d14d 100755 --- a/cmd/zitadel/caos_local.sh +++ b/cmd/zitadel/caos_local.sh @@ -11,6 +11,8 @@ export ZITADEL_TRACING_FRACTION=0.1 export ZITADEL_TRACING_ENDPOINT=localhost:9096 export ZITADEL_TRACING_TYPE=google +export ZITADEL_METRICS_TYPE=otel + # Log export ZITADEL_LOG_LEVEL=debug diff --git a/cmd/zitadel/main.go b/cmd/zitadel/main.go index 776fd3bb5b..c1004a077f 100644 --- a/cmd/zitadel/main.go +++ b/cmd/zitadel/main.go @@ -3,6 +3,7 @@ package main import ( "context" "flag" + metrics "github.com/caos/zitadel/internal/telemetry/metrics/config" "github.com/caos/logging" admin_es "github.com/caos/zitadel/internal/admin/repository/eventsourcing" @@ -21,7 +22,7 @@ import ( mgmt_es "github.com/caos/zitadel/internal/management/repository/eventsourcing" "github.com/caos/zitadel/internal/notification" "github.com/caos/zitadel/internal/setup" - tracing "github.com/caos/zitadel/internal/tracing/config" + tracing "github.com/caos/zitadel/internal/telemetry/tracing/config" "github.com/caos/zitadel/internal/ui" "github.com/caos/zitadel/internal/ui/console" "github.com/caos/zitadel/internal/ui/login" @@ -30,6 +31,7 @@ import ( type Config struct { Log logging.Config Tracing tracing.TracingConfig + Metrics metrics.MetricsConfig InternalAuthZ internal_authz.Config SystemDefaults sd.SystemDefaults @@ -125,14 +127,16 @@ func startUI(ctx context.Context, conf *Config, authRepo *auth_es.EsRepository) } func startAPI(ctx context.Context, conf *Config, authZRepo *authz_repo.EsRepository, authRepo *auth_es.EsRepository) { - apis := api.Create(conf.API, conf.InternalAuthZ, authZRepo, conf.SystemDefaults) roles := make([]string, len(conf.InternalAuthZ.RolePermissionMappings)) for i, role := range conf.InternalAuthZ.RolePermissionMappings { roles[i] = role.Role } + adminRepo, err := admin_es.Start(ctx, conf.Admin, conf.SystemDefaults, roles) + logging.Log("API-D42tq").OnError(err).Fatal("error starting auth repo") + + apis := api.Create(conf.API, conf.InternalAuthZ, authZRepo, authRepo, adminRepo, conf.SystemDefaults) + if *adminEnabled { - adminRepo, err := admin_es.Start(ctx, conf.Admin, conf.SystemDefaults, roles) - logging.Log("API-D42tq").OnError(err).Fatal("error starting auth repo") apis.RegisterServer(ctx, admin.CreateServer(adminRepo)) } if *managementEnabled { diff --git a/cmd/zitadel/startup.yaml b/cmd/zitadel/startup.yaml index 1d3fff247f..88f5a5e1c9 100644 --- a/cmd/zitadel/startup.yaml +++ b/cmd/zitadel/startup.yaml @@ -11,6 +11,11 @@ Tracing: Fraction: $ZITADEL_TRACING_FRACTION Endpoint: $ZITADEL_TRACING_ENDPOINT +Metrics: + Type: 'otel' + Config: + MeterName: 'github.com/caos/zitadel' + AuthZ: Repository: Eventstore: @@ -224,7 +229,7 @@ UI: Login: Handler: BaseURL: '$ZITADEL_ACCOUNTS' - OidcAuthCallbackURL: '$ZITADEL_AUTHORIZE/authorize/' + OidcAuthCallbackURL: '$ZITADEL_AUTHORIZE/authorize/callback?id=' ZitadelURL: '$ZITADEL_CONSOLE' LanguageCookieName: 'caos.zitadel.login.lang' DefaultLanguage: 'de' diff --git a/console/src/app/pages/iam/iam-views/iam-views.component.html b/console/src/app/pages/iam/iam-views/iam-views.component.html index 074e7be296..ce36d3b615 100644 --- a/console/src/app/pages/iam/iam-views/iam-views.component.html +++ b/console/src/app/pages/iam/iam-views/iam-views.component.html @@ -18,13 +18,20 @@ {{view.processedSequence}} - - {{ 'IAM.VIEWS.TIMESTAMP' | translate }} + + {{ 'IAM.VIEWS.EVENTTIMESTAMP' | translate }} - {{view?.viewTimestamp | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} + {{view?.eventTimestamp | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} + + {{ 'IAM.VIEWS.LASTSPOOL' | translate }} + + {{view?.lastSuccessfulSpoolerRun | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} + + + @@ -41,4 +48,4 @@ - \ No newline at end of file + diff --git a/console/src/app/pages/iam/iam-views/iam-views.component.ts b/console/src/app/pages/iam/iam-views/iam-views.component.ts index 343649a372..c1f07a3fb5 100644 --- a/console/src/app/pages/iam/iam-views/iam-views.component.ts +++ b/console/src/app/pages/iam/iam-views/iam-views.component.ts @@ -21,7 +21,7 @@ export class IamViewsComponent implements AfterViewInit { @ViewChild(MatPaginator) public paginator!: MatPaginator; public dataSource!: MatTableDataSource; - public displayedColumns: string[] = ['viewName', 'database', 'sequence', 'timestamp', 'actions']; + public displayedColumns: string[] = ['viewName', 'database', 'sequence', 'eventTimestamp', 'lastSuccessfulSpoolerRun', 'actions']; private loadingSubject: BehaviorSubject = new BehaviorSubject(false); public loading$: Observable = this.loadingSubject.asObservable(); diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index 4feeac9ab1..d505ea77e7 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -392,7 +392,8 @@ "VIEWNAME":"Name", "DATABASE":"Datenbank", "SEQUENCE":"Sequenz", - "TIMESTAMP":"Zeitstempel", + "EVENTTIMESTAMP":"Event Zeitstempel", + "LASTSPOOL": "Erfolgreicher Durchlauf", "ACTIONS":"Aktionen", "CLEAR":"Aufräumen", "CLEARED":"View wurde erfolgreich zurückgesetzt!", diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index 9fa4a9e2cc..3072b341fd 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -392,7 +392,8 @@ "VIEWNAME":"Name", "DATABASE":"Database", "SEQUENCE":"Sequence", - "TIMESTAMP":"Timestamp", + "EVENTTIMESTAMP":"Timestamp", + "LASTSPOOL": "Successful spool", "ACTIONS":"Actions", "CLEAR":"Clear", "CLEARED":"View was successfully cleared!", diff --git a/go.mod b/go.mod index 71a00780fa..202a94667e 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/allegro/bigcache v1.2.1 github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc github.com/caos/logging v0.0.2 - github.com/caos/oidc v0.13.0 + github.com/caos/oidc v0.13.1 github.com/cockroachdb/cockroach-go/v2 v2.0.8 github.com/envoyproxy/protoc-gen-validate v0.4.1 github.com/ghodss/yaml v1.0.0 @@ -23,6 +23,7 @@ require ( github.com/golang/mock v1.4.4 github.com/golang/protobuf v1.4.3 github.com/golang/snappy v0.0.2 // indirect + github.com/google/go-cmp v0.5.3 // indirect github.com/gorilla/csrf v1.7.0 github.com/gorilla/mux v1.8.0 github.com/gorilla/schema v1.2.0 @@ -44,6 +45,8 @@ require ( github.com/mitchellh/reflectwalk v1.0.1 // indirect github.com/nicksnyder/go-i18n/v2 v2.1.1 github.com/pquerna/otp v1.2.0 + github.com/prometheus/client_golang v1.8.0 // indirect + github.com/prometheus/common v0.15.0 // indirect github.com/rakyll/statik v0.1.7 github.com/rs/cors v1.7.0 github.com/sony/sonyflake v1.0.0 @@ -53,12 +56,13 @@ require ( go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.13.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.13.0 go.opentelemetry.io/otel v0.13.0 + go.opentelemetry.io/otel/exporters/metric/prometheus v0.13.0 go.opentelemetry.io/otel/exporters/otlp v0.13.0 go.opentelemetry.io/otel/exporters/stdout v0.13.0 go.opentelemetry.io/otel/sdk v0.13.0 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 // indirect - golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 // indirect + golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect golang.org/x/text v0.3.4 golang.org/x/tools v0.0.0-20201103235415-b653051172e4 google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index a9d98c7947..e6b4d8a17a 100644 --- a/go.sum +++ b/go.sum @@ -57,6 +57,7 @@ github.com/DataDog/sketches-go v0.0.1 h1:RtG+76WKgZuz6FIaGsjoPePmadDBkuD/KC6+ZWu github.com/DataDog/sketches-go v0.0.1/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v0.13.0 h1:fjKUtfldCPIF4nIzAAj3LzP8Lrd3DuRIMiFdOsj4fLc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v0.13.0/go.mod h1:q/paYxLXKVhwfC3lzLfhtL54fAx14wzMN9DundQOBMc= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= @@ -65,10 +66,19 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw= github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/ajstarks/svgo v0.0.0-20200725142600-7a3c8b57fecb h1:EVl3FJLQCzSbgBezKo/1A4ADnJ4mtJZ0RvnNzDJ44nY= github.com/ajstarks/svgo v0.0.0-20200725142600-7a3c8b57fecb/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= @@ -76,8 +86,22 @@ github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5z github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.0.3 h1:vkLuvpK4fmtSCuo60+yC63p7y0BmQ8gm5ZXGuBCJyXg= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -86,8 +110,10 @@ github.com/caos/logging v0.0.2 h1:ebg5C/HN0ludYR+WkvnFjwSExF4wvyiWPyWGcKMYsoo= github.com/caos/logging v0.0.2 h1:ebg5C/HN0ludYR+WkvnFjwSExF4wvyiWPyWGcKMYsoo= github.com/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= github.com/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= -github.com/caos/oidc v0.13.0 h1:l1IKrqV3HaS2TfseuC5kOR3DdEPfY9AbJXuZ7dsIEQo= -github.com/caos/oidc v0.13.0/go.mod h1:dLvfYUiAt9ORfl77L/KkcWuR/N0ll8Ry1nD2ERsamDY= +github.com/caos/oidc v0.13.1 h1:8890xd3XJpev5xuU4Dn2l49c1lCA3Qd1xu4KsPSVo38= +github.com/caos/oidc v0.13.1/go.mod h1:dLvfYUiAt9ORfl77L/KkcWuR/N0ll8Ry1nD2ERsamDY= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -99,6 +125,7 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5O github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU= @@ -107,9 +134,15 @@ github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go/v2 v2.0.8 h1:50C/7ptrrfdxDccCjDU0xsdeBca+S0/AYW4Mo8RyzFE= github.com/cockroachdb/cockroach-go/v2 v2.0.8/go.mod h1:nkf7rUmgPdawp3EwRjXIumihI2AYg9usGNWbJ2hsJqI= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -119,6 +152,13 @@ github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9r github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E= @@ -129,8 +169,12 @@ github.com/envoyproxy/protoc-gen-validate v0.4.1 h1:7dLaJvASGRD7X49jSCSXXHwKPm0Z github.com/envoyproxy/protoc-gen-validate v0.4.1/go.mod h1:E+IEazqdaWv3FrnGtZIu3b9fPFMK8AzeTTrk9SfVwWs= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= @@ -138,10 +182,14 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= @@ -152,6 +200,9 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -161,6 +212,7 @@ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= @@ -192,6 +244,7 @@ github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= @@ -212,10 +265,13 @@ github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github/v31 v31.0.0 h1:JJUxlP9lFK+ziXKimTCprajMApV1ecWD4NB6CCb0plo= github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= @@ -234,6 +290,7 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -242,10 +299,14 @@ github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3 h1:eHv/jVY/JNop1xg2J9cBb4EzyMpWZoNCP1BslSAIkOI= github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3/go.mod h1:h/KNeRx7oYU4SpA4SoY7W2/NxDKEEVuwA6j9A27L4OI= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/csrf v1.7.0 h1:mMPjV5/3Zd460xCavIkppUdvnl5fPXMpv2uz2Zyg7/Y= github.com/gorilla/csrf v1.7.0/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -254,15 +315,39 @@ github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7 h1:ux/56T2xqZO/3cP1I2F86qpeoYPCOzk+KF/UH/Ar+lk= github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c= @@ -273,6 +358,8 @@ github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1 h1:KUDFlmBg2buRWNzIcwLlKvfcnujcHQRQ1As1LoaCLAM= github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -322,11 +409,21 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kevinburke/go-types v0.0.0-20200309064045-f2d4aea18a7a h1:Z7+SSApKiwPjNic+NF9+j7h657Uyvdp/jA3iTKhpj4E= github.com/kevinburke/go-types v0.0.0-20200309064045-f2d4aea18a7a/go.mod h1:/Pk5i/SqYdYv1cie5wGwoZ4P6TpgMi+Yf58mtJSHdOw= github.com/kevinburke/go.uuid v1.2.0 h1:+1qP8NdkJfgOSTrrrUuA7h0djr1VY77HFXYjR+zUcUo= @@ -343,6 +440,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -360,46 +458,128 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.4.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nicksnyder/go-i18n/v2 v2.1.1 h1:ATCOanRDlrfKVB4WHAdJnLEqZtDmKYsweqsOUYflnBU= github.com/nicksnyder/go-i18n/v2 v2.1.1/go.mod h1:d++QJC9ZVf7pa48qrsRWhMJ5pSHIPmS3OLqK1niyLxs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= +github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= @@ -412,22 +592,38 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0 h1:uPRuwkWF4J6fGsJ2R0Gn2jB1EQiav9k3S6CSdygQJXY= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20200419222939-1884f454f8ea h1:jaXWVFZ98/ihXniiDzqNXQgMSgklX4kjfDWZTE3ZtdU= github.com/shopspring/decimal v0.0.0-20200419222939-1884f454f8ea/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM= github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4= github.com/spf13/afero v1.3.3 h1:p5gZEKLYoL7wh8VrJesMaYeNxdEd1v3cb4irOk9zB54= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.3.4 h1:8q6vk3hthlpb2SouZcnBVKboxWQWMDNF38bwholZrJc= github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -441,10 +637,14 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 h1:5u+EJUQiosu3JFX0XS0qTf5FznsMOzTjGqavBGuCbo0= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2/go.mod h1:4kyMkleCiLkgY6z8gK5BkI01ChBtxR0ro3I1ZDcGM3w= github.com/ttacon/libphonenumber v1.1.0 h1:tC6kE4t8UI4OqQVQjW5q8gSWhG2wnY5moEpSEORdYm4= github.com/ttacon/libphonenumber v1.1.0/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32 h1:5tjfNdR2ki3yYQ842+eX2sQHeiwpKJ0RnHO4IYOc4V8= @@ -452,6 +652,10 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zenazn/goji v0.9.0 h1:RSQQAbXGArQ0dIDEq+PI6WqN6if+5KHu6x2Cx/GXLTQ= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -469,6 +673,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.13.0 h1:dnZy1af go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.13.0/go.mod h1:SeQm4RTCcZ2/hlMSTuHb7nwIROe5odBtgfKx+7MMqEs= go.opentelemetry.io/otel v0.13.0 h1:2isEnyzjjJZq6r2EKMsFj4TxiQiexsM04AVhwbR/oBA= go.opentelemetry.io/otel v0.13.0/go.mod h1:dlSNewoRYikTkotEnxdmuBHgzT+k/idJSfDv/FxEnOY= +go.opentelemetry.io/otel/exporters/metric/prometheus v0.13.0 h1:Jf7AdsEoHKtNTWxXLj/g9XGjsGpdk0otEf0lx00r2Ps= +go.opentelemetry.io/otel/exporters/metric/prometheus v0.13.0/go.mod h1:Tyh3ACxU9a1tu1mF4at7xvNu+BaiPThrr5XZmsoIW7g= go.opentelemetry.io/otel/exporters/otlp v0.13.0 h1:iithmYmMAfLFgCW5TcRXHpXR5NTWO7nGtX3WcBiusVE= go.opentelemetry.io/otel/exporters/otlp v0.13.0/go.mod h1:YHH58UrGcqCKtBkY7sl3zPKpxBzfC1HUUYMRQONJJ9E= go.opentelemetry.io/otel/exporters/stdout v0.13.0 h1:A+XiGIPQbGoJoBOJfKAKnZyiUSjSWvL3XWETUvtom5k= @@ -478,11 +684,17 @@ go.opentelemetry.io/otel/sdk v0.13.0/go.mod h1:dKvLH8Uu8LcEPlSAUsfW7kMGaJBhk/1NY go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -490,6 +702,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -540,13 +753,20 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -600,8 +820,14 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2By golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -621,7 +847,9 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab h1:FvshnhkKW+LO3HWHodML8kuVX8rnJTxKm9dFPuI68UM= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -639,12 +867,15 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -654,11 +885,13 @@ golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -666,6 +899,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -678,6 +912,8 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -685,6 +921,7 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -721,6 +958,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -746,6 +984,7 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.34.0 h1:k40adF3uR+6x/+hO5Dh4ZFUqFp67vxvbpafFiJxl10A= google.golang.org/api v0.34.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -760,6 +999,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -796,10 +1036,15 @@ google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201103154000-415bd0cd5df6 h1:rMoZiLTOobSD3eg30lPMcFkBFNSyKUQQIQlw/hsAXME= google.golang.org/genproto v0.0.0-20201103154000-415bd0cd5df6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -831,20 +1076,31 @@ google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEG google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec h1:RlWgLqCMMIYYEVcAR5MDsuHlVkaIPDAF+5Dehzg8L5A= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= @@ -853,6 +1109,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -868,3 +1125,5 @@ rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/internal/admin/repository/administrator.go b/internal/admin/repository/administrator.go index f091146a0b..026a293c9e 100644 --- a/internal/admin/repository/administrator.go +++ b/internal/admin/repository/administrator.go @@ -8,6 +8,7 @@ import ( type AdministratorRepository interface { GetFailedEvents(context.Context) ([]*model.FailedEvent, error) RemoveFailedEvent(context.Context, *model.FailedEvent) error - GetViews(context.Context) ([]*model.View, error) - ClearView(ctx context.Context, db, view string) error + GetViews() ([]*model.View, error) + GetSpoolerDiv(db, viewName string) int64 + ClearView(ctx context.Context, db, viewName string) error } diff --git a/internal/admin/repository/eventsourcing/eventstore/administrator.go b/internal/admin/repository/eventsourcing/eventstore/administrator.go index d0af36284e..52ab002cac 100644 --- a/internal/admin/repository/eventsourcing/eventstore/administrator.go +++ b/internal/admin/repository/eventsourcing/eventstore/administrator.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view" view_model "github.com/caos/zitadel/internal/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) var dbList = []string{"management", "auth", "authz", "adminapi", "notification"} @@ -31,7 +32,7 @@ func (repo *AdministratorRepo) RemoveFailedEvent(ctx context.Context, failedEven return repo.View.RemoveFailedEvent(failedEvent.Database, repository.FailedEventFromModel(failedEvent)) } -func (repo *AdministratorRepo) GetViews(ctx context.Context) ([]*view_model.View, error) { +func (repo *AdministratorRepo) GetViews() ([]*view_model.View, error) { views := make([]*view_model.View, 0) for _, db := range dbList { sequences, err := repo.View.AllCurrentSequences(db) @@ -45,6 +46,16 @@ func (repo *AdministratorRepo) GetViews(ctx context.Context) ([]*view_model.View return views, nil } +func (repo *AdministratorRepo) GetSpoolerDiv(database, view string) int64 { + sequence, err := repo.View.GetCurrentSequence(database, view) + if err != nil { + + return 0 + } + divDuration := time.Now().Sub(sequence.LastSuccessfulSpoolerRun) + return divDuration.Milliseconds() +} + func (repo *AdministratorRepo) ClearView(ctx context.Context, database, view string) error { return repo.View.ClearView(database, view) } diff --git a/internal/admin/repository/eventsourcing/eventstore/iam.go b/internal/admin/repository/eventsourcing/eventstore/iam.go index 5fcc5f936e..617cca2636 100644 --- a/internal/admin/repository/eventsourcing/eventstore/iam.go +++ b/internal/admin/repository/eventsourcing/eventstore/iam.go @@ -14,7 +14,7 @@ import ( iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing" iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model" org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" usr_model "github.com/caos/zitadel/internal/user/model" usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing" ) @@ -68,7 +68,7 @@ func (repo *IAMRepository) SearchIAMMembers(ctx context.Context, request *iam_mo } if err == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -170,7 +170,7 @@ func (repo *IAMRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo } if err == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -262,7 +262,7 @@ func (repo *IAMRepository) SearchDefaultIDPProviders(ctx context.Context, reques } if err == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } diff --git a/internal/admin/repository/eventsourcing/eventstore/org.go b/internal/admin/repository/eventsourcing/eventstore/org.go index b0c706b4c6..78400eae29 100644 --- a/internal/admin/repository/eventsourcing/eventstore/org.go +++ b/internal/admin/repository/eventsourcing/eventstore/org.go @@ -6,7 +6,7 @@ import ( "github.com/caos/zitadel/internal/errors" iam_model "github.com/caos/zitadel/internal/iam/model" iam_view "github.com/caos/zitadel/internal/iam/repository/view/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" "github.com/caos/logging" admin_model "github.com/caos/zitadel/internal/admin/model" @@ -101,7 +101,7 @@ func (repo *OrgRepo) SearchOrgs(ctx context.Context, query *org_model.OrgSearchR } if err == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } diff --git a/internal/admin/repository/eventsourcing/handler/handler.go b/internal/admin/repository/eventsourcing/handler/handler.go index 31115d9878..25f3b69223 100644 --- a/internal/admin/repository/eventsourcing/handler/handler.go +++ b/internal/admin/repository/eventsourcing/handler/handler.go @@ -41,7 +41,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, ev &IDPConfig{handler: handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount}}, &LabelPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount}}, &LoginPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount}}, - &IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount}, + &IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount}, systemDefaults: defaults, iamEvents: repos.IamEvents, orgEvents: repos.OrgEvents}, &User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, eventstore: eventstore, orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, systemDefaults: defaults}, @@ -49,7 +49,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, ev &PasswordAgePolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordAgePolicy"), errorCount}}, &PasswordLockoutPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordLockoutPolicy"), errorCount}}, &OrgIAMPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount}}, - &ExternalIDP{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, + &ExternalIDP{handler: handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount}, orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, systemDefaults: defaults}, } } diff --git a/internal/admin/repository/eventsourcing/handler/iam_member.go b/internal/admin/repository/eventsourcing/handler/iam_member.go index 906e9f6aa3..d3c9b77bb6 100644 --- a/internal/admin/repository/eventsourcing/handler/iam_member.go +++ b/internal/admin/repository/eventsourcing/handler/iam_member.go @@ -72,14 +72,14 @@ func (m *IamMember) processIamMember(event *models.Event) (err error) { if err != nil { return err } - return m.view.DeleteIAMMember(event.AggregateID, member.UserID, event.Sequence) + return m.view.DeleteIAMMember(event.AggregateID, member.UserID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedIAMMemberSequence(event.Sequence) + return m.view.ProcessedIAMMemberSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutIAMMember(member, member.Sequence) + return m.view.PutIAMMember(member, member.Sequence, event.CreationDate) } func (m *IamMember) processUser(event *models.Event) (err error) { @@ -94,7 +94,7 @@ func (m *IamMember) processUser(event *models.Event) (err error) { return err } if len(members) == 0 { - return m.view.ProcessedIAMMemberSequence(event.Sequence) + return m.view.ProcessedIAMMemberSequence(event.Sequence, event.CreationDate) } user, err := m.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -103,11 +103,11 @@ func (m *IamMember) processUser(event *models.Event) (err error) { for _, member := range members { m.fillUserData(member, user) } - return m.view.PutIAMMembers(members, event.Sequence) + return m.view.PutIAMMembers(members, event.Sequence, event.CreationDate) case usr_es_model.UserRemoved: - return m.view.DeleteIAMMembersByUserID(event.AggregateID, event.Sequence) + return m.view.DeleteIAMMembersByUserID(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedIAMMemberSequence(event.Sequence) + return m.view.ProcessedIAMMemberSequence(event.Sequence, event.CreationDate) } return nil } @@ -137,3 +137,7 @@ func (m *IamMember) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Ld9ow", "id", event.AggregateID).WithError(err).Warn("something went wrong in iammember handler") return spooler.HandleError(event, err, m.view.GetLatestIAMMemberFailedEvent, m.view.ProcessedIAMMemberFailedEvent, m.view.ProcessedIAMMemberSequence, m.errorCountUntilSkip) } + +func (m *IamMember) OnSuccess() error { + return spooler.HandleSuccess(m.view.UpdateIAMMemberSpoolerRunTimestamp) +} diff --git a/internal/admin/repository/eventsourcing/handler/idp_config.go b/internal/admin/repository/eventsourcing/handler/idp_config.go index 1f6500cc0f..be8d43d7dc 100644 --- a/internal/admin/repository/eventsourcing/handler/idp_config.go +++ b/internal/admin/repository/eventsourcing/handler/idp_config.go @@ -19,12 +19,12 @@ const ( idpConfigTable = "adminapi.idp_configs" ) -func (m *IDPConfig) ViewModel() string { +func (i *IDPConfig) ViewModel() string { return idpConfigTable } -func (m *IDPConfig) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestIDPConfigSequence() +func (i *IDPConfig) EventQuery() (*models.SearchQuery, error) { + sequence, err := i.view.GetLatestIDPConfigSequence() if err != nil { return nil, err } @@ -33,15 +33,15 @@ func (m *IDPConfig) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *IDPConfig) Reduce(event *models.Event) (err error) { +func (i *IDPConfig) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate: - err = m.processIDPConfig(event) + err = i.processIDPConfig(event) } return err } -func (m *IDPConfig) processIDPConfig(event *models.Event) (err error) { +func (i *IDPConfig) processIDPConfig(event *models.Event) (err error) { idp := new(iam_view_model.IDPConfigView) switch event.Type { case model.IDPConfigAdded: @@ -53,7 +53,7 @@ func (m *IDPConfig) processIDPConfig(event *models.Event) (err error) { if err != nil { return err } - idp, err = m.view.IDPConfigByID(idp.IDPConfigID) + idp, err = i.view.IDPConfigByID(idp.IDPConfigID) if err != nil { return err } @@ -63,17 +63,21 @@ func (m *IDPConfig) processIDPConfig(event *models.Event) (err error) { if err != nil { return err } - return m.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence) + return i.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedIDPConfigSequence(event.Sequence) + return i.view.ProcessedIDPConfigSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutIDPConfig(idp, idp.Sequence) + return i.view.PutIDPConfig(idp, idp.Sequence, event.CreationDate) } -func (m *IDPConfig) OnError(event *models.Event, err error) error { +func (i *IDPConfig) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Mslo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp config handler") - return spooler.HandleError(event, err, m.view.GetLatestIDPConfigFailedEvent, m.view.ProcessedIDPConfigFailedEvent, m.view.ProcessedIDPConfigSequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, i.view.GetLatestIDPConfigFailedEvent, i.view.ProcessedIDPConfigFailedEvent, i.view.ProcessedIDPConfigSequence, i.errorCountUntilSkip) +} + +func (i *IDPConfig) OnSuccess() error { + return spooler.HandleSuccess(i.view.UpdateIDPConfigSpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/handler/idp_providers.go b/internal/admin/repository/eventsourcing/handler/idp_providers.go index 0613ae7fa5..0e27ee11ec 100644 --- a/internal/admin/repository/eventsourcing/handler/idp_providers.go +++ b/internal/admin/repository/eventsourcing/handler/idp_providers.go @@ -27,12 +27,12 @@ const ( idpProviderTable = "adminapi.idp_providers" ) -func (m *IDPProvider) ViewModel() string { +func (i *IDPProvider) ViewModel() string { return idpProviderTable } -func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestIDPProviderSequence() +func (i *IDPProvider) EventQuery() (*models.SearchQuery, error) { + sequence, err := i.view.GetLatestIDPProviderSequence() if err != nil { return nil, err } @@ -41,15 +41,15 @@ func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *IDPProvider) Reduce(event *models.Event) (err error) { +func (i *IDPProvider) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate, org_es_model.OrgAggregate: - err = m.processIdpProvider(event) + err = i.processIdpProvider(event) } return err } -func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { +func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) { provider := new(iam_view_model.IDPProviderView) switch event.Type { case model.LoginPolicyIDPProviderAdded, org_es_model.LoginPolicyIDPProviderAdded: @@ -57,64 +57,68 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { if err != nil { return err } - err = m.fillData(provider) + err = i.fillData(provider) case model.LoginPolicyIDPProviderRemoved, model.LoginPolicyIDPProviderCascadeRemoved, org_es_model.LoginPolicyIDPProviderRemoved, org_es_model.LoginPolicyIDPProviderCascadeRemoved: err = provider.SetData(event) if err != nil { return err } - return m.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence) + return i.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence, event.CreationDate) case model.IDPConfigChanged, org_es_model.IDPConfigChanged: esConfig := new(iam_view_model.IDPConfigView) providerType := iam_model.IDPProviderTypeSystem - if event.AggregateID != m.systemDefaults.IamID { + if event.AggregateID != i.systemDefaults.IamID { providerType = iam_model.IDPProviderTypeOrg } esConfig.AppendEvent(providerType, event) - providers, err := m.view.IDPProvidersByIdpConfigID(esConfig.IDPConfigID) + providers, err := i.view.IDPProvidersByIdpConfigID(esConfig.IDPConfigID) if err != nil { return err } - config, err := m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID) + config, err := i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID) if err != nil { return err } for _, provider := range providers { - m.fillConfigData(provider, config) + i.fillConfigData(provider, config) } - return m.view.PutIDPProviders(event.Sequence, providers...) + return i.view.PutIDPProviders(event.Sequence, event.CreationDate, providers...) default: - return m.view.ProcessedIDPProviderSequence(event.Sequence) + return i.view.ProcessedIDPProviderSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutIDPProvider(provider, provider.Sequence) + return i.view.PutIDPProvider(provider, provider.Sequence, event.CreationDate) } -func (m *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) { +func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) { var config *iam_model.IDPConfig if provider.IDPProviderType == int32(iam_model.IDPProviderTypeSystem) { - config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, provider.IDPConfigID) + config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, provider.IDPConfigID) } else { - config, err = m.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID) + config, err = i.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID) } if err != nil { return err } - m.fillConfigData(provider, config) + i.fillConfigData(provider, config) return nil } -func (m *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *iam_model.IDPConfig) { +func (i *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *iam_model.IDPConfig) { provider.Name = config.Name provider.StylingType = int32(config.StylingType) provider.IDPConfigType = int32(config.Type) provider.IDPState = int32(config.State) } -func (m *IDPProvider) OnError(event *models.Event, err error) error { +func (i *IDPProvider) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Msj8c", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler") - return spooler.HandleError(event, err, m.view.GetLatestIDPProviderFailedEvent, m.view.ProcessedIDPProviderFailedEvent, m.view.ProcessedIDPProviderSequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, i.view.GetLatestIDPProviderFailedEvent, i.view.ProcessedIDPProviderFailedEvent, i.view.ProcessedIDPProviderSequence, i.errorCountUntilSkip) +} + +func (i *IDPProvider) OnSuccess() error { + return spooler.HandleSuccess(i.view.UpdateIDPProviderSpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/handler/label_policy.go b/internal/admin/repository/eventsourcing/handler/label_policy.go index 5226b5e3dd..3f81c0060d 100644 --- a/internal/admin/repository/eventsourcing/handler/label_policy.go +++ b/internal/admin/repository/eventsourcing/handler/label_policy.go @@ -18,12 +18,12 @@ const ( labelPolicyTable = "adminapi.label_policies" ) -func (m *LabelPolicy) ViewModel() string { +func (p *LabelPolicy) ViewModel() string { return labelPolicyTable } -func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestLabelPolicySequence() +func (p *LabelPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestLabelPolicySequence() if err != nil { return nil, err } @@ -32,35 +32,39 @@ func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *LabelPolicy) Reduce(event *models.Event) (err error) { +func (p *LabelPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate: - err = m.processLabelPolicy(event) + err = p.processLabelPolicy(event) } return err } -func (m *LabelPolicy) processLabelPolicy(event *models.Event) (err error) { +func (p *LabelPolicy) processLabelPolicy(event *models.Event) (err error) { policy := new(iam_model.LabelPolicyView) switch event.Type { case model.LabelPolicyAdded: err = policy.AppendEvent(event) case model.LabelPolicyChanged: - policy, err = m.view.LabelPolicyByAggregateID(event.AggregateID) + policy, err = p.view.LabelPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) default: - return m.view.ProcessedLabelPolicySequence(event.Sequence) + return p.view.ProcessedLabelPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutLabelPolicy(policy, policy.Sequence) + return p.view.PutLabelPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *LabelPolicy) OnError(event *models.Event, err error) error { +func (p *LabelPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Wj8sf", "id", event.AggregateID).WithError(err).Warn("something went wrong in label policy handler") - return spooler.HandleError(event, err, m.view.GetLatestLabelPolicyFailedEvent, m.view.ProcessedLabelPolicyFailedEvent, m.view.ProcessedLabelPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestLabelPolicyFailedEvent, p.view.ProcessedLabelPolicyFailedEvent, p.view.ProcessedLabelPolicySequence, p.errorCountUntilSkip) +} + +func (p *LabelPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateLabelPolicySpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/handler/login_policy.go b/internal/admin/repository/eventsourcing/handler/login_policy.go index 9f4a20988f..c24100ca69 100644 --- a/internal/admin/repository/eventsourcing/handler/login_policy.go +++ b/internal/admin/repository/eventsourcing/handler/login_policy.go @@ -18,12 +18,12 @@ const ( loginPolicyTable = "adminapi.login_policies" ) -func (m *LoginPolicy) ViewModel() string { +func (p *LoginPolicy) ViewModel() string { return loginPolicyTable } -func (m *LoginPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestLoginPolicySequence() +func (p *LoginPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestLoginPolicySequence() if err != nil { return nil, err } @@ -32,15 +32,15 @@ func (m *LoginPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *LoginPolicy) Reduce(event *models.Event) (err error) { +func (p *LoginPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate: - err = m.processLoginPolicy(event) + err = p.processLoginPolicy(event) } return err } -func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { +func (p *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { policy := new(iam_model.LoginPolicyView) switch event.Type { case model.LoginPolicyAdded: @@ -50,21 +50,25 @@ func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { model.LoginPolicySecondFactorRemoved, model.LoginPolicyMultiFactorAdded, model.LoginPolicyMultiFactorRemoved: - policy, err = m.view.LoginPolicyByAggregateID(event.AggregateID) + policy, err = p.view.LoginPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) default: - return m.view.ProcessedLoginPolicySequence(event.Sequence) + return p.view.ProcessedLoginPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutLoginPolicy(policy, policy.Sequence) + return p.view.PutLoginPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *LoginPolicy) OnError(event *models.Event, err error) error { +func (p *LoginPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Wj8sf", "id", event.AggregateID).WithError(err).Warn("something went wrong in login policy handler") - return spooler.HandleError(event, err, m.view.GetLatestLoginPolicyFailedEvent, m.view.ProcessedLoginPolicyFailedEvent, m.view.ProcessedLoginPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestLoginPolicyFailedEvent, p.view.ProcessedLoginPolicyFailedEvent, p.view.ProcessedLoginPolicySequence, p.errorCountUntilSkip) +} + +func (p *LoginPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateLoginPolicySpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/handler/org.go b/internal/admin/repository/eventsourcing/handler/org.go index fafe94a74c..eb64e60ea7 100644 --- a/internal/admin/repository/eventsourcing/handler/org.go +++ b/internal/admin/repository/eventsourcing/handler/org.go @@ -53,13 +53,17 @@ func (o *Org) Reduce(event *es_models.Event) error { return err } default: - return o.view.ProcessedOrgSequence(event.Sequence) + return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate) } - return o.view.PutOrg(org) + return o.view.PutOrg(org, event.CreationDate) } func (o *Org) OnError(event *es_models.Event, spoolerErr error) error { logging.LogWithFields("SPOOL-ls9ew", "id", event.AggregateID).WithError(spoolerErr).Warn("something went wrong in project app handler") return spooler.HandleError(event, spoolerErr, o.view.GetLatestOrgFailedEvent, o.view.ProcessedOrgFailedEvent, o.view.ProcessedOrgSequence, o.errorCountUntilSkip) } + +func (o *Org) OnSuccess() error { + return spooler.HandleSuccess(o.view.UpdateOrgSpoolerRunTimestamp) +} diff --git a/internal/admin/repository/eventsourcing/handler/org_iam_policy.go b/internal/admin/repository/eventsourcing/handler/org_iam_policy.go index cb49e33efb..99c01e73e1 100644 --- a/internal/admin/repository/eventsourcing/handler/org_iam_policy.go +++ b/internal/admin/repository/eventsourcing/handler/org_iam_policy.go @@ -19,12 +19,12 @@ const ( orgIAMPolicyTable = "adminapi.org_iam_policies" ) -func (m *OrgIAMPolicy) ViewModel() string { +func (p *OrgIAMPolicy) ViewModel() string { return orgIAMPolicyTable } -func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestOrgIAMPolicySequence() +func (p *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestOrgIAMPolicySequence() if err != nil { return nil, err } @@ -33,37 +33,41 @@ func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *OrgIAMPolicy) Reduce(event *models.Event) (err error) { +func (p *OrgIAMPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: - err = m.processOrgIAMPolicy(event) + err = p.processOrgIAMPolicy(event) } return err } -func (m *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) { +func (p *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) { policy := new(iam_model.OrgIAMPolicyView) switch event.Type { case iam_es_model.OrgIAMPolicyAdded, model.OrgIAMPolicyAdded: err = policy.AppendEvent(event) case iam_es_model.OrgIAMPolicyChanged, model.OrgIAMPolicyChanged: - policy, err = m.view.OrgIAMPolicyByAggregateID(event.AggregateID) + policy, err = p.view.OrgIAMPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) case model.OrgIAMPolicyRemoved: - return m.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence) + return p.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedOrgIAMPolicySequence(event.Sequence) + return p.view.ProcessedOrgIAMPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutOrgIAMPolicy(policy, policy.Sequence) + return p.view.PutOrgIAMPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *OrgIAMPolicy) OnError(event *models.Event, err error) error { +func (p *OrgIAMPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Wm8fs", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgIAM policy handler") - return spooler.HandleError(event, err, m.view.GetLatestOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicySequence, p.errorCountUntilSkip) +} + +func (p *OrgIAMPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateOrgIAMPolicySpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/handler/password_age_policy.go b/internal/admin/repository/eventsourcing/handler/password_age_policy.go index bf56af86ef..3608ec446e 100644 --- a/internal/admin/repository/eventsourcing/handler/password_age_policy.go +++ b/internal/admin/repository/eventsourcing/handler/password_age_policy.go @@ -19,12 +19,12 @@ const ( passwordAgePolicyTable = "adminapi.password_age_policies" ) -func (m *PasswordAgePolicy) ViewModel() string { +func (p *PasswordAgePolicy) ViewModel() string { return passwordAgePolicyTable } -func (m *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestPasswordAgePolicySequence() +func (p *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestPasswordAgePolicySequence() if err != nil { return nil, err } @@ -33,37 +33,41 @@ func (m *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *PasswordAgePolicy) Reduce(event *models.Event) (err error) { +func (p *PasswordAgePolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: - err = m.processPasswordAgePolicy(event) + err = p.processPasswordAgePolicy(event) } return err } -func (m *PasswordAgePolicy) processPasswordAgePolicy(event *models.Event) (err error) { +func (p *PasswordAgePolicy) processPasswordAgePolicy(event *models.Event) (err error) { policy := new(iam_model.PasswordAgePolicyView) switch event.Type { case iam_es_model.PasswordAgePolicyAdded, model.PasswordAgePolicyAdded: err = policy.AppendEvent(event) case iam_es_model.PasswordAgePolicyChanged, model.PasswordAgePolicyChanged: - policy, err = m.view.PasswordAgePolicyByAggregateID(event.AggregateID) + policy, err = p.view.PasswordAgePolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) case model.PasswordAgePolicyRemoved: - return m.view.DeletePasswordAgePolicy(event.AggregateID, event.Sequence) + return p.view.DeletePasswordAgePolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedPasswordAgePolicySequence(event.Sequence) + return p.view.ProcessedPasswordAgePolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutPasswordAgePolicy(policy, policy.Sequence) + return p.view.PutPasswordAgePolicy(policy, policy.Sequence, event.CreationDate) } -func (m *PasswordAgePolicy) OnError(event *models.Event, err error) error { +func (p *PasswordAgePolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-nD8sie", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordAge policy handler") - return spooler.HandleError(event, err, m.view.GetLatestPasswordAgePolicyFailedEvent, m.view.ProcessedPasswordAgePolicyFailedEvent, m.view.ProcessedPasswordAgePolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestPasswordAgePolicyFailedEvent, p.view.ProcessedPasswordAgePolicyFailedEvent, p.view.ProcessedPasswordAgePolicySequence, p.errorCountUntilSkip) +} + +func (p *PasswordAgePolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateProcessedPasswordAgePolicySpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/handler/password_complexity_policy.go b/internal/admin/repository/eventsourcing/handler/password_complexity_policy.go index 2eeb6cf759..f1d2898218 100644 --- a/internal/admin/repository/eventsourcing/handler/password_complexity_policy.go +++ b/internal/admin/repository/eventsourcing/handler/password_complexity_policy.go @@ -19,12 +19,12 @@ const ( passwordComplexityPolicyTable = "adminapi.password_complexity_policies" ) -func (m *PasswordComplexityPolicy) ViewModel() string { +func (p *PasswordComplexityPolicy) ViewModel() string { return passwordComplexityPolicyTable } -func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestPasswordComplexityPolicySequence() +func (p *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestPasswordComplexityPolicySequence() if err != nil { return nil, err } @@ -33,37 +33,41 @@ func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) { +func (p *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: - err = m.processPasswordComplexityPolicy(event) + err = p.processPasswordComplexityPolicy(event) } return err } -func (m *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) { +func (p *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) { policy := new(iam_model.PasswordComplexityPolicyView) switch event.Type { case iam_es_model.PasswordComplexityPolicyAdded, model.PasswordComplexityPolicyAdded: err = policy.AppendEvent(event) case iam_es_model.PasswordComplexityPolicyChanged, model.PasswordComplexityPolicyChanged: - policy, err = m.view.PasswordComplexityPolicyByAggregateID(event.AggregateID) + policy, err = p.view.PasswordComplexityPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) case model.PasswordComplexityPolicyRemoved: - return m.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence) + return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedPasswordComplexityPolicySequence(event.Sequence) + return p.view.ProcessedPasswordComplexityPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutPasswordComplexityPolicy(policy, policy.Sequence) + return p.view.PutPasswordComplexityPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *PasswordComplexityPolicy) OnError(event *models.Event, err error) error { +func (p *PasswordComplexityPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Wm8fs", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordComplexity policy handler") - return spooler.HandleError(event, err, m.view.GetLatestPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicySequence, p.errorCountUntilSkip) +} + +func (p *PasswordComplexityPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdatePasswordComplexityPolicySpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/handler/password_lockout_policy.go b/internal/admin/repository/eventsourcing/handler/password_lockout_policy.go index bd71ab054d..fd087adda7 100644 --- a/internal/admin/repository/eventsourcing/handler/password_lockout_policy.go +++ b/internal/admin/repository/eventsourcing/handler/password_lockout_policy.go @@ -19,12 +19,12 @@ const ( passwordLockoutPolicyTable = "adminapi.password_lockout_policies" ) -func (m *PasswordLockoutPolicy) ViewModel() string { +func (p *PasswordLockoutPolicy) ViewModel() string { return passwordLockoutPolicyTable } -func (m *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestPasswordLockoutPolicySequence() +func (p *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestPasswordLockoutPolicySequence() if err != nil { return nil, err } @@ -33,37 +33,41 @@ func (m *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *PasswordLockoutPolicy) Reduce(event *models.Event) (err error) { +func (p *PasswordLockoutPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: - err = m.processPasswordLockoutPolicy(event) + err = p.processPasswordLockoutPolicy(event) } return err } -func (m *PasswordLockoutPolicy) processPasswordLockoutPolicy(event *models.Event) (err error) { +func (p *PasswordLockoutPolicy) processPasswordLockoutPolicy(event *models.Event) (err error) { policy := new(iam_model.PasswordLockoutPolicyView) switch event.Type { case iam_es_model.PasswordLockoutPolicyAdded, model.PasswordLockoutPolicyAdded: err = policy.AppendEvent(event) case iam_es_model.PasswordLockoutPolicyChanged, model.PasswordLockoutPolicyChanged: - policy, err = m.view.PasswordLockoutPolicyByAggregateID(event.AggregateID) + policy, err = p.view.PasswordLockoutPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) case model.PasswordLockoutPolicyRemoved: - return m.view.DeletePasswordLockoutPolicy(event.AggregateID, event.Sequence) + return p.view.DeletePasswordLockoutPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedPasswordLockoutPolicySequence(event.Sequence) + return p.view.ProcessedPasswordLockoutPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutPasswordLockoutPolicy(policy, policy.Sequence) + return p.view.PutPasswordLockoutPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *PasswordLockoutPolicy) OnError(event *models.Event, err error) error { +func (p *PasswordLockoutPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-nD8sie", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordLockout policy handler") - return spooler.HandleError(event, err, m.view.GetLatestPasswordLockoutPolicyFailedEvent, m.view.ProcessedPasswordLockoutPolicyFailedEvent, m.view.ProcessedPasswordLockoutPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestPasswordLockoutPolicyFailedEvent, p.view.ProcessedPasswordLockoutPolicyFailedEvent, p.view.ProcessedPasswordLockoutPolicySequence, p.errorCountUntilSkip) +} + +func (p *PasswordLockoutPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdatePasswordLockoutPolicySpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/handler/user.go b/internal/admin/repository/eventsourcing/handler/user.go index 8a4105d131..f93c49c048 100644 --- a/internal/admin/repository/eventsourcing/handler/user.go +++ b/internal/admin/repository/eventsourcing/handler/user.go @@ -110,14 +110,14 @@ func (u *User) ProcessUser(event *models.Event) (err error) { } err = u.fillLoginNames(user) case es_model.UserRemoved: - return u.view.DeleteUser(event.AggregateID, event.Sequence) + return u.view.DeleteUser(event.AggregateID, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserSequence(event.Sequence) + return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return u.view.PutUser(user, user.Sequence) + return u.view.PutUser(user, user.Sequence, event.CreationDate) } func (u *User) ProcessOrg(event *models.Event) (err error) { @@ -131,7 +131,7 @@ func (u *User) ProcessOrg(event *models.Event) (err error) { case org_es_model.OrgDomainPrimarySet: return u.fillPreferredLoginNamesOnOrgUsers(event) default: - return u.view.ProcessedUserSequence(event.Sequence) + return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) } } @@ -154,7 +154,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.SetLoginNames(policy, org.Domains) } - return u.view.PutUsers(users, event.Sequence) + return u.view.PutUsers(users, event.Sequence, event.CreationDate) } func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { @@ -179,7 +179,7 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) } - return u.view.PutUsers(users, event.Sequence) + return u.view.PutUsers(users, event.Sequence, event.CreationDate) } func (u *User) fillLoginNames(user *view_model.UserView) (err error) { @@ -203,3 +203,7 @@ func (u *User) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-vLmwQ", "id", event.AggregateID).WithError(err).Warn("something went wrong in user handler") return spooler.HandleError(event, err, u.view.GetLatestUserFailedEvent, u.view.ProcessedUserFailedEvent, u.view.ProcessedUserSequence, u.errorCountUntilSkip) } + +func (u *User) OnSuccess() error { + return spooler.HandleSuccess(u.view.UpdateUserSpoolerRunTimestamp) +} diff --git a/internal/admin/repository/eventsourcing/handler/user_external_idps.go b/internal/admin/repository/eventsourcing/handler/user_external_idps.go index b9c74c1c89..cc4d979dc3 100644 --- a/internal/admin/repository/eventsourcing/handler/user_external_idps.go +++ b/internal/admin/repository/eventsourcing/handler/user_external_idps.go @@ -30,12 +30,12 @@ const ( externalIDPTable = "adminapi.user_external_idps" ) -func (m *ExternalIDP) ViewModel() string { +func (i *ExternalIDP) ViewModel() string { return externalIDPTable } -func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestExternalIDPSequence() +func (i *ExternalIDP) EventQuery() (*models.SearchQuery, error) { + sequence, err := i.view.GetLatestExternalIDPSequence() if err != nil { return nil, err } @@ -44,17 +44,17 @@ func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *ExternalIDP) Reduce(event *models.Event) (err error) { +func (i *ExternalIDP) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.UserAggregate: - err = m.processUser(event) + err = i.processUser(event) case iam_es_model.IAMAggregate, org_es_model.OrgAggregate: - err = m.processIdpConfig(event) + err = i.processIdpConfig(event) } return err } -func (m *ExternalIDP) processUser(event *models.Event) (err error) { +func (i *ExternalIDP) processUser(event *models.Event) (err error) { externalIDP := new(usr_view_model.ExternalIDPView) switch event.Type { case model.HumanExternalIDPAdded: @@ -62,25 +62,25 @@ func (m *ExternalIDP) processUser(event *models.Event) (err error) { if err != nil { return err } - err = m.fillData(externalIDP) + err = i.fillData(externalIDP) case model.HumanExternalIDPRemoved, model.HumanExternalIDPCascadeRemoved: err = externalIDP.SetData(event) if err != nil { return err } - return m.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence) + return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence, event.CreationDate) case model.UserRemoved: - return m.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence) + return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedExternalIDPSequence(event.Sequence) + return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutExternalIDP(externalIDP, externalIDP.Sequence) + return i.view.PutExternalIDP(externalIDP, externalIDP.Sequence, event.CreationDate) } -func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) { +func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) { switch event.Type { case iam_es_model.IDPConfigChanged, org_es_model.IDPConfigChanged: configView := new(iam_view_model.IDPConfigView) @@ -90,45 +90,49 @@ func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) { } else { configView.AppendEvent(iam_model.IDPProviderTypeOrg, event) } - exterinalIDPs, err := m.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID) + exterinalIDPs, err := i.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID) if err != nil { return err } if event.AggregateType == iam_es_model.IAMAggregate { - config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) + config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) } else { - config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) + config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) } if err != nil { return err } for _, provider := range exterinalIDPs { - m.fillConfigData(provider, config) + i.fillConfigData(provider, config) } - return m.view.PutExternalIDPs(event.Sequence, exterinalIDPs...) + return i.view.PutExternalIDPs(event.Sequence, event.CreationDate, exterinalIDPs...) default: - return m.view.ProcessedExternalIDPSequence(event.Sequence) + return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) } return nil } -func (m *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error { - config, err := m.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID) +func (i *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error { + config, err := i.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID) if caos_errs.IsNotFound(err) { - config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, externalIDP.IDPConfigID) + config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, externalIDP.IDPConfigID) } if err != nil { return err } - m.fillConfigData(externalIDP, config) + i.fillConfigData(externalIDP, config) return nil } -func (m *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) { +func (i *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) { externalIDP.IDPName = config.Name } -func (m *ExternalIDP) OnError(event *models.Event, err error) error { +func (i *ExternalIDP) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-4Rsu8", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler") - return spooler.HandleError(event, err, m.view.GetLatestExternalIDPFailedEvent, m.view.ProcessedExternalIDPFailedEvent, m.view.ProcessedExternalIDPSequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, i.view.GetLatestExternalIDPFailedEvent, i.view.ProcessedExternalIDPFailedEvent, i.view.ProcessedExternalIDPSequence, i.errorCountUntilSkip) +} + +func (i *ExternalIDP) OnSuccess() error { + return spooler.HandleSuccess(i.view.UpdateExternalIDPSpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/view/external_idps.go b/internal/admin/repository/eventsourcing/view/external_idps.go index de919a589a..8f21e7de86 100644 --- a/internal/admin/repository/eventsourcing/view/external_idps.go +++ b/internal/admin/repository/eventsourcing/view/external_idps.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -32,44 +33,48 @@ func (v *View) SearchExternalIDPs(request *usr_model.ExternalIDPSearchRequest) ( return view.SearchExternalIDPs(v.Db, externalIDPTable, request) } -func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64) error { +func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64, eventTimestamp time.Time) error { err := view.PutExternalIDP(v.Db, externalIDPTable, externalIDP) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence) + return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) } -func (v *View) PutExternalIDPs(sequence uint64, externalIDPs ...*model.ExternalIDPView) error { +func (v *View) PutExternalIDPs(sequence uint64, eventTimestamp time.Time, externalIDPs ...*model.ExternalIDPView) error { err := view.PutExternalIDPs(v.Db, externalIDPTable, externalIDPs...) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence) + return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) } -func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64) error { +func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteExternalIDP(v.Db, externalIDPTable, externalUserID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedExternalIDPSequence(eventSequence) + return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64) error { +func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteExternalIDPsByUserID(v.Db, externalIDPTable, userID) if err != nil { return err } - return v.ProcessedExternalIDPSequence(eventSequence) + return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestExternalIDPSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(externalIDPTable) } -func (v *View) ProcessedExternalIDPSequence(eventSequence uint64) error { - return v.saveCurrentSequence(externalIDPTable, eventSequence) +func (v *View) ProcessedExternalIDPSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(externalIDPTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateExternalIDPSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(externalIDPTable) } func (v *View) GetLatestExternalIDPFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/iam_member.go b/internal/admin/repository/eventsourcing/view/iam_member.go index 2e27aa4182..250a0042fa 100644 --- a/internal/admin/repository/eventsourcing/view/iam_member.go +++ b/internal/admin/repository/eventsourcing/view/iam_member.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -24,44 +25,48 @@ func (v *View) IAMMembersByUserID(userID string) ([]*model.IAMMemberView, error) return view.IAMMembersByUserID(v.Db, iamMemberTable, userID) } -func (v *View) PutIAMMember(org *model.IAMMemberView, sequence uint64) error { +func (v *View) PutIAMMember(org *model.IAMMemberView, sequence uint64, eventTimestamp time.Time) error { err := view.PutIAMMember(v.Db, iamMemberTable, org) if err != nil { return err } - return v.ProcessedIAMMemberSequence(sequence) + return v.ProcessedIAMMemberSequence(sequence, eventTimestamp) } -func (v *View) PutIAMMembers(members []*model.IAMMemberView, sequence uint64) error { +func (v *View) PutIAMMembers(members []*model.IAMMemberView, sequence uint64, eventTimestamp time.Time) error { err := view.PutIAMMembers(v.Db, iamMemberTable, members...) if err != nil { return err } - return v.ProcessedIAMMemberSequence(sequence) + return v.ProcessedIAMMemberSequence(sequence, eventTimestamp) } -func (v *View) DeleteIAMMember(iamID, userID string, eventSequence uint64) error { +func (v *View) DeleteIAMMember(iamID, userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIAMMember(v.Db, iamMemberTable, iamID, userID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIAMMemberSequence(eventSequence) + return v.ProcessedIAMMemberSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteIAMMembersByUserID(userID string, eventSequence uint64) error { +func (v *View) DeleteIAMMembersByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIAMMembersByUserID(v.Db, iamMemberTable, userID) if err != nil { return err } - return v.ProcessedIAMMemberSequence(eventSequence) + return v.ProcessedIAMMemberSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestIAMMemberSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(iamMemberTable) } -func (v *View) ProcessedIAMMemberSequence(eventSequence uint64) error { - return v.saveCurrentSequence(iamMemberTable, eventSequence) +func (v *View) ProcessedIAMMemberSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(iamMemberTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateIAMMemberSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(iamMemberTable) } func (v *View) GetLatestIAMMemberFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/idp_configs.go b/internal/admin/repository/eventsourcing/view/idp_configs.go index d6deab1212..197c37d09b 100644 --- a/internal/admin/repository/eventsourcing/view/idp_configs.go +++ b/internal/admin/repository/eventsourcing/view/idp_configs.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -20,28 +21,32 @@ func (v *View) SearchIDPConfigs(request *iam_model.IDPConfigSearchRequest) ([]*m return view.SearchIDPs(v.Db, idpConfigTable, request) } -func (v *View) PutIDPConfig(idp *model.IDPConfigView, sequence uint64) error { +func (v *View) PutIDPConfig(idp *model.IDPConfigView, sequence uint64, eventTimestamp time.Time) error { err := view.PutIDP(v.Db, idpConfigTable, idp) if err != nil { return err } - return v.ProcessedIDPConfigSequence(sequence) + return v.ProcessedIDPConfigSequence(sequence, eventTimestamp) } -func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64) error { +func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIDP(v.Db, idpConfigTable, idpID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPConfigSequence(eventSequence) + return v.ProcessedIDPConfigSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestIDPConfigSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(idpConfigTable) } -func (v *View) ProcessedIDPConfigSequence(eventSequence uint64) error { - return v.saveCurrentSequence(idpConfigTable, eventSequence) +func (v *View) ProcessedIDPConfigSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(idpConfigTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateIDPConfigSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(idpConfigTable) } func (v *View) GetLatestIDPConfigFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/idp_providers.go b/internal/admin/repository/eventsourcing/view/idp_providers.go index 5c4931abf6..10b5886945 100644 --- a/internal/admin/repository/eventsourcing/view/idp_providers.go +++ b/internal/admin/repository/eventsourcing/view/idp_providers.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -24,36 +25,40 @@ func (v *View) SearchIDPProviders(request *iam_model.IDPProviderSearchRequest) ( return view.SearchIDPProviders(v.Db, idpProviderTable, request) } -func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64) error { +func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64, eventTimestamp time.Time) error { err := view.PutIDPProvider(v.Db, idpProviderTable, provider) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence) + return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) } -func (v *View) PutIDPProviders(sequence uint64, providers ...*model.IDPProviderView) error { +func (v *View) PutIDPProviders(sequence uint64, eventTimestamp time.Time, providers ...*model.IDPProviderView) error { err := view.PutIDPProviders(v.Db, idpProviderTable, providers...) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence) + return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) } -func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64) error { +func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIDPProvider(v.Db, idpProviderTable, aggregateID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPProviderSequence(eventSequence) + return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestIDPProviderSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(idpProviderTable) } -func (v *View) ProcessedIDPProviderSequence(eventSequence uint64) error { - return v.saveCurrentSequence(idpProviderTable, eventSequence) +func (v *View) ProcessedIDPProviderSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(idpProviderTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateIDPProviderSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(idpProviderTable) } func (v *View) GetLatestIDPProviderFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/label_policies.go b/internal/admin/repository/eventsourcing/view/label_policies.go index 113859894f..f4e921ac1c 100644 --- a/internal/admin/repository/eventsourcing/view/label_policies.go +++ b/internal/admin/repository/eventsourcing/view/label_policies.go @@ -4,6 +4,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -14,20 +15,24 @@ func (v *View) LabelPolicyByAggregateID(aggregateID string) (*model.LabelPolicyV return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTable, aggregateID) } -func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, sequence uint64) error { +func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy) if err != nil { return err } - return v.ProcessedLabelPolicySequence(sequence) + return v.ProcessedLabelPolicySequence(sequence, eventTimestamp) } func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(labelPolicyTable) } -func (v *View) ProcessedLabelPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(labelPolicyTable, eventSequence) +func (v *View) ProcessedLabelPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(labelPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateLabelPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(labelPolicyTable) } func (v *View) GetLatestLabelPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/login_policies.go b/internal/admin/repository/eventsourcing/view/login_policies.go index 8e37e57729..03e4451ffb 100644 --- a/internal/admin/repository/eventsourcing/view/login_policies.go +++ b/internal/admin/repository/eventsourcing/view/login_policies.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyV return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID) } -func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64) error { +func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutLoginPolicy(v.Db, loginPolicyTable, policy) if err != nil { return err } - return v.ProcessedLoginPolicySequence(sequence) + return v.ProcessedLoginPolicySequence(sequence, eventTimestamp) } -func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedLoginPolicySequence(eventSequence) + return v.ProcessedLoginPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestLoginPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(loginPolicyTable) } -func (v *View) ProcessedLoginPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(loginPolicyTable, eventSequence) +func (v *View) ProcessedLoginPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(loginPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateLoginPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(loginPolicyTable) } func (v *View) GetLatestLoginPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/org.go b/internal/admin/repository/eventsourcing/view/org.go index 2c580ab012..ee9f9fb113 100644 --- a/internal/admin/repository/eventsourcing/view/org.go +++ b/internal/admin/repository/eventsourcing/view/org.go @@ -5,6 +5,7 @@ import ( org_view "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -19,12 +20,12 @@ func (v *View) SearchOrgs(query *org_model.OrgSearchRequest) ([]*model.OrgView, return org_view.SearchOrgs(v.Db, orgTable, query) } -func (v *View) PutOrg(org *model.OrgView) error { +func (v *View) PutOrg(org *model.OrgView, eventTimestamp time.Time) error { err := org_view.PutOrg(v.Db, orgTable, org) if err != nil { return err } - return v.ProcessedOrgSequence(org.Sequence) + return v.ProcessedOrgSequence(org.Sequence, eventTimestamp) } func (v *View) GetLatestOrgFailedEvent(sequence uint64) (*repository.FailedEvent, error) { @@ -35,10 +36,14 @@ func (v *View) ProcessedOrgFailedEvent(failedEvent *repository.FailedEvent) erro return v.saveFailedEvent(failedEvent) } +func (v *View) UpdateOrgSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(orgTable) +} + func (v *View) GetLatestOrgSequence() (*repository.CurrentSequence, error) { return v.latestSequence(orgTable) } -func (v *View) ProcessedOrgSequence(eventSequence uint64) error { - return v.saveCurrentSequence(orgTable, eventSequence) +func (v *View) ProcessedOrgSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(orgTable, eventSequence, eventTimestamp) } diff --git a/internal/admin/repository/eventsourcing/view/org_iam_policy.go b/internal/admin/repository/eventsourcing/view/org_iam_policy.go index 57196f7eaf..3168a78152 100644 --- a/internal/admin/repository/eventsourcing/view/org_iam_policy.go +++ b/internal/admin/repository/eventsourcing/view/org_iam_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) OrgIAMPolicyByAggregateID(aggregateID string) (*model.OrgIAMPolic return view.GetOrgIAMPolicyByAggregateID(v.Db, orgIAMPolicyTable, aggregateID) } -func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64) error { +func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutOrgIAMPolicy(v.Db, orgIAMPolicyTable, policy) if err != nil { return err } - return v.ProcessedOrgIAMPolicySequence(sequence) + return v.ProcessedOrgIAMPolicySequence(sequence, eventTimestamp) } -func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteOrgIAMPolicy(v.Db, orgIAMPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedOrgIAMPolicySequence(eventSequence) + return v.ProcessedOrgIAMPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestOrgIAMPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(orgIAMPolicyTable) } -func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence) +func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateOrgIAMPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(orgIAMPolicyTable) } func (v *View) GetLatestOrgIAMPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/password_age_policy.go b/internal/admin/repository/eventsourcing/view/password_age_policy.go index 915f2cb50d..419b537830 100644 --- a/internal/admin/repository/eventsourcing/view/password_age_policy.go +++ b/internal/admin/repository/eventsourcing/view/password_age_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) PasswordAgePolicyByAggregateID(aggregateID string) (*model.Passwo return view.GetPasswordAgePolicyByAggregateID(v.Db, passwordAgePolicyTable, aggregateID) } -func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, sequence uint64) error { +func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutPasswordAgePolicy(v.Db, passwordAgePolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordAgePolicySequence(sequence) + return v.ProcessedPasswordAgePolicySequence(sequence, eventTimestamp) } -func (v *View) DeletePasswordAgePolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeletePasswordAgePolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeletePasswordAgePolicy(v.Db, passwordAgePolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordAgePolicySequence(eventSequence) + return v.ProcessedPasswordAgePolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestPasswordAgePolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(passwordAgePolicyTable) } -func (v *View) ProcessedPasswordAgePolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(passwordAgePolicyTable, eventSequence) +func (v *View) ProcessedPasswordAgePolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(passwordAgePolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateProcessedPasswordAgePolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(passwordAgePolicyTable) } func (v *View) GetLatestPasswordAgePolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/password_complexity_policy.go b/internal/admin/repository/eventsourcing/view/password_complexity_policy.go index 554a32ca0d..2b1af7d375 100644 --- a/internal/admin/repository/eventsourcing/view/password_complexity_policy.go +++ b/internal/admin/repository/eventsourcing/view/password_complexity_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) PasswordComplexityPolicyByAggregateID(aggregateID string) (*model return view.GetPasswordComplexityPolicyByAggregateID(v.Db, passwordComplexityPolicyTable, aggregateID) } -func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64) error { +func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutPasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordComplexityPolicySequence(sequence) + return v.ProcessedPasswordComplexityPolicySequence(sequence, eventTimestamp) } -func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeletePasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordComplexityPolicySequence(eventSequence) + return v.ProcessedPasswordComplexityPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestPasswordComplexityPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(passwordComplexityPolicyTable) } -func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence) +func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdatePasswordComplexityPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(passwordComplexityPolicyTable) } func (v *View) GetLatestPasswordComplexityPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/password_lockout_policy.go b/internal/admin/repository/eventsourcing/view/password_lockout_policy.go index 4ee6d38623..d20643d37c 100644 --- a/internal/admin/repository/eventsourcing/view/password_lockout_policy.go +++ b/internal/admin/repository/eventsourcing/view/password_lockout_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) PasswordLockoutPolicyByAggregateID(aggregateID string) (*model.Pa return view.GetPasswordLockoutPolicyByAggregateID(v.Db, passwordLockoutPolicyTable, aggregateID) } -func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, sequence uint64) error { +func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutPasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordLockoutPolicySequence(sequence) + return v.ProcessedPasswordLockoutPolicySequence(sequence, eventTimestamp) } -func (v *View) DeletePasswordLockoutPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeletePasswordLockoutPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeletePasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordLockoutPolicySequence(eventSequence) + return v.ProcessedPasswordLockoutPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestPasswordLockoutPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(passwordLockoutPolicyTable) } -func (v *View) ProcessedPasswordLockoutPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(passwordLockoutPolicyTable, eventSequence) +func (v *View) ProcessedPasswordLockoutPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(passwordLockoutPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdatePasswordLockoutPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(passwordLockoutPolicyTable) } func (v *View) GetLatestPasswordLockoutPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/admin/repository/eventsourcing/view/sequence.go b/internal/admin/repository/eventsourcing/view/sequence.go index 3d01519477..cda4580a6b 100644 --- a/internal/admin/repository/eventsourcing/view/sequence.go +++ b/internal/admin/repository/eventsourcing/view/sequence.go @@ -2,14 +2,15 @@ package view import ( "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( sequencesTable = "adminapi.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence) +func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimeStamp time.Time) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimeStamp) } func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { @@ -20,6 +21,24 @@ func (v *View) AllCurrentSequences(db string) ([]*repository.CurrentSequence, er return repository.AllCurrentSequences(v.Db, db+".current_sequences") } +func (v *View) updateSpoolerRunSequence(viewName string) error { + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + if err != nil { + return err + } + if currentSequence.ViewName == "" { + currentSequence.ViewName = viewName + } + currentSequence.LastSuccessfulSpoolerRun = time.Now() + return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) +} + +func (v *View) GetCurrentSequence(db, viewName string) (*repository.CurrentSequence, error) { + sequenceTable := db + ".current_sequences" + fullView := db + "." + viewName + return repository.LatestSequence(v.Db, sequenceTable, fullView) +} + func (v *View) ClearView(db, viewName string) error { truncateView := db + "." + viewName sequenceTable := db + ".current_sequences" diff --git a/internal/admin/repository/eventsourcing/view/user.go b/internal/admin/repository/eventsourcing/view/user.go index 1dcdcebc5f..75fb8878e8 100644 --- a/internal/admin/repository/eventsourcing/view/user.go +++ b/internal/admin/repository/eventsourcing/view/user.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -39,39 +40,43 @@ func (v *View) UserMfas(userID string) ([]*usr_model.MultiFactor, error) { return view.UserMfas(v.Db, userTable, userID) } -func (v *View) PutUsers(user []*model.UserView, sequence uint64) error { +func (v *View) PutUsers(user []*model.UserView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUsers(v.Db, userTable, user...) if err != nil { return err } - return v.ProcessedUserSequence(sequence) + return v.ProcessedUserSequence(sequence, eventTimestamp) } -func (v *View) PutUser(user *model.UserView, sequence uint64) error { +func (v *View) PutUser(user *model.UserView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUser(v.Db, userTable, user) if err != nil { return err } if sequence != 0 { - return v.ProcessedUserSequence(sequence) + return v.ProcessedUserSequence(sequence, eventTimestamp) } return nil } -func (v *View) DeleteUser(userID string, eventSequence uint64) error { +func (v *View) DeleteUser(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUser(v.Db, userTable, userID) if err != nil { return nil } - return v.ProcessedUserSequence(eventSequence) + return v.ProcessedUserSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestUserSequence() (*repository.CurrentSequence, error) { return v.latestSequence(userTable) } -func (v *View) ProcessedUserSequence(eventSequence uint64) error { - return v.saveCurrentSequence(userTable, eventSequence) +func (v *View) ProcessedUserSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(userTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateUserSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(userTable) } func (v *View) GetLatestUserFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/api/api.go b/internal/api/api.go index 7de3ff62ba..a0225af53a 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -2,6 +2,12 @@ package api import ( "context" + admin_es "github.com/caos/zitadel/internal/admin/repository/eventsourcing" + auth_es "github.com/caos/zitadel/internal/auth/repository/eventsourcing" + "github.com/caos/zitadel/internal/telemetry/metrics" + "github.com/caos/zitadel/internal/telemetry/metrics/otel" + view_model "github.com/caos/zitadel/internal/view/model" + "go.opentelemetry.io/otel/api/metric" "net/http" "github.com/caos/logging" @@ -16,7 +22,7 @@ import ( "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/errors" iam_model "github.com/caos/zitadel/internal/iam/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) type Config struct { @@ -30,19 +36,33 @@ type API struct { verifier *authz.TokenVerifier serverPort string health health + auth auth + admin admin } + type health interface { Health(ctx context.Context) error IamByID(ctx context.Context) (*iam_model.IAM, error) VerifierClientID(ctx context.Context, appName string) (string, error) } -func Create(config Config, authZ authz.Config, authZRepo *authz_es.EsRepository, sd systemdefaults.SystemDefaults) *API { +type auth interface { + ActiveUserSessionCount() int64 +} + +type admin interface { + GetViews() ([]*view_model.View, error) + GetSpoolerDiv(database, viewName string) int64 +} + +func Create(config Config, authZ authz.Config, authZRepo *authz_es.EsRepository, authRepo *auth_es.EsRepository, adminRepo *admin_es.EsRepository, sd systemdefaults.SystemDefaults) *API { api := &API{ serverPort: config.GRPC.ServerPort, } api.verifier = authz.Start(authZRepo) api.health = authZRepo + api.auth = authRepo + api.admin = adminRepo api.grpcServer = server.CreateServer(api.verifier, authZ, sd.DefaultLanguage) api.gatewayHandler = server.CreateGatewayHandler(config.GRPC) api.RegisterHandler("", api.healthHandler()) @@ -92,6 +112,7 @@ func (a *API) healthHandler() http.Handler { handler.HandleFunc("/ready", handleReadiness(checks)) handler.HandleFunc("/validate", handleValidate(checks)) handler.HandleFunc("/clientID", a.handleClientID) + handler.Handle("/metrics", a.handleMetrics()) return handler } @@ -132,6 +153,48 @@ func (a *API) handleClientID(w http.ResponseWriter, r *http.Request) { http_util.MarshalJSON(w, id, nil, http.StatusOK) } +func (a *API) handleMetrics() http.Handler { + a.registerActiveSessionCounters() + a.registerSpoolerDivCounters() + return metrics.GetExporter() +} + +func (a *API) registerActiveSessionCounters() { + metrics.RegisterValueObserver( + metrics.ActiveSessionCounter, + metrics.ActiveSessionCounterDescription, + func(ctx context.Context, result metric.Int64ObserverResult) { + result.Observe( + a.auth.ActiveUserSessionCount(), + ) + }, + ) +} + +func (a *API) registerSpoolerDivCounters() { + views, err := a.admin.GetViews() + if err != nil { + logging.Log("API-3M8sd").WithError(err).Error("could not read views for metrics") + return + } + metrics.RegisterValueObserver( + metrics.SpoolerDivCounter, + metrics.SpoolerDivCounterDescription, + func(ctx context.Context, result metric.Int64ObserverResult) { + for _, view := range views { + labels := map[string]interface{}{ + metrics.Database: view.Database, + metrics.ViewName: view.ViewName, + } + result.Observe( + a.admin.GetSpoolerDiv(view.Database, view.ViewName), + otel.MapToKeyValue(labels)..., + ) + } + }, + ) +} + type ValidationFunction func(ctx context.Context) error func validate(ctx context.Context, validations []ValidationFunction) []error { diff --git a/internal/api/authz/authorization.go b/internal/api/authz/authorization.go index 740bff3431..7ae5e838f4 100644 --- a/internal/api/authz/authorization.go +++ b/internal/api/authz/authorization.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) const ( diff --git a/internal/api/authz/context.go b/internal/api/authz/context.go index 576fe2c13a..4880a7373e 100644 --- a/internal/api/authz/context.go +++ b/internal/api/authz/context.go @@ -6,7 +6,7 @@ import ( "github.com/caos/zitadel/internal/api/grpc" http_util "github.com/caos/zitadel/internal/api/http" "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) type key int diff --git a/internal/api/authz/permissions.go b/internal/api/authz/permissions.go index 6147deeac9..8023152ca9 100644 --- a/internal/api/authz/permissions.go +++ b/internal/api/authz/permissions.go @@ -4,7 +4,7 @@ import ( "context" "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) func getUserMethodPermissions(ctx context.Context, t *TokenVerifier, requiredPerm string, authConfig Config) (_ context.Context, _ []string, err error) { diff --git a/internal/api/authz/token.go b/internal/api/authz/token.go index a646cdb8ef..463b7396c2 100644 --- a/internal/api/authz/token.go +++ b/internal/api/authz/token.go @@ -6,7 +6,7 @@ import ( "sync" caos_errs "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) const ( diff --git a/internal/api/grpc/admin/administrator.go b/internal/api/grpc/admin/administrator.go index 58fbefaf6c..1d855a61f2 100644 --- a/internal/api/grpc/admin/administrator.go +++ b/internal/api/grpc/admin/administrator.go @@ -10,7 +10,7 @@ import ( ) func (s *Server) GetViews(ctx context.Context, _ *empty.Empty) (_ *admin.Views, err error) { - views, err := s.administrator.GetViews(ctx) + views, err := s.administrator.GetViews() if err != nil { return nil, err } diff --git a/internal/api/grpc/admin/administrator_converter.go b/internal/api/grpc/admin/administrator_converter.go index 7dc640a8a4..1f93d2496c 100644 --- a/internal/api/grpc/admin/administrator_converter.go +++ b/internal/api/grpc/admin/administrator_converter.go @@ -26,14 +26,17 @@ func failedEventsFromModel(failedEvents []*view_model.FailedEvent) []*admin.Fail } func viewFromModel(view *view_model.View) *admin.View { - timestamp, err := ptypes.TimestampProto(view.CurrentTimestamp) + eventTimestamp, err := ptypes.TimestampProto(view.EventTimestamp) + logging.Log("GRPC-KSo03").OnError(err).Debug("unable to parse timestamp") + lastSpool, err := ptypes.TimestampProto(view.EventTimestamp) logging.Log("GRPC-KSo03").OnError(err).Debug("unable to parse timestamp") return &admin.View{ - Database: view.Database, - ViewName: view.ViewName, - ProcessedSequence: view.CurrentSequence, - ViewTimestamp: timestamp, + Database: view.Database, + ViewName: view.ViewName, + ProcessedSequence: view.CurrentSequence, + EventTimestamp: eventTimestamp, + LastSuccessfulSpoolerRun: lastSpool, } } diff --git a/internal/api/grpc/admin/probes.go b/internal/api/grpc/admin/probes.go index 632471bf2d..0a67a7f967 100644 --- a/internal/api/grpc/admin/probes.go +++ b/internal/api/grpc/admin/probes.go @@ -2,7 +2,6 @@ package admin import ( "context" - "github.com/golang/protobuf/ptypes/empty" ) diff --git a/internal/api/grpc/auth/user_converter.go b/internal/api/grpc/auth/user_converter.go index 376904b7d8..c6866ecf23 100644 --- a/internal/api/grpc/auth/user_converter.go +++ b/internal/api/grpc/auth/user_converter.go @@ -12,7 +12,7 @@ import ( "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/eventstore/models" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/pkg/grpc/auth" "github.com/caos/zitadel/pkg/grpc/message" diff --git a/internal/api/grpc/server/gateway.go b/internal/api/grpc/server/gateway.go index 1833e905ff..675b0b41a9 100644 --- a/internal/api/grpc/server/gateway.go +++ b/internal/api/grpc/server/gateway.go @@ -14,7 +14,7 @@ import ( client_middleware "github.com/caos/zitadel/internal/api/grpc/client/middleware" http_util "github.com/caos/zitadel/internal/api/http" http_mw "github.com/caos/zitadel/internal/api/http/middleware" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) const ( @@ -129,7 +129,8 @@ func createDialOptions(g Gateway) []grpc.DialOption { } func addInterceptors(handler http.Handler, g Gateway) http.Handler { - handler = http_mw.DefaultTraceHandler(handler) + handler = http_mw.DefaultMetricsHandler(handler) + handler = http_mw.DefaultTelemetryHandler(handler) handler = http_mw.NoCacheInterceptor(handler) if interceptor, ok := g.(grpcGatewayCustomInterceptor); ok { handler = interceptor.GatewayHTTPInterceptor(handler) diff --git a/internal/api/grpc/server/middleware/auth_interceptor.go b/internal/api/grpc/server/middleware/auth_interceptor.go index e46f661098..347e0b18f9 100644 --- a/internal/api/grpc/server/middleware/auth_interceptor.go +++ b/internal/api/grpc/server/middleware/auth_interceptor.go @@ -10,7 +10,7 @@ import ( "github.com/caos/zitadel/internal/api/authz" grpc_util "github.com/caos/zitadel/internal/api/grpc" "github.com/caos/zitadel/internal/api/http" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Config) grpc.UnaryServerInterceptor { diff --git a/internal/api/grpc/server/middleware/metrics_interceptor.go b/internal/api/grpc/server/middleware/metrics_interceptor.go new file mode 100644 index 0000000000..4dcf6cc8a8 --- /dev/null +++ b/internal/api/grpc/server/middleware/metrics_interceptor.go @@ -0,0 +1,86 @@ +package middleware + +import ( + "context" + "strings" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "google.golang.org/grpc" + "google.golang.org/grpc/status" + + _ "github.com/caos/zitadel/internal/statik" + "github.com/caos/zitadel/internal/telemetry/metrics" +) + +const ( + GrpcMethod = "grpc_method" + ReturnCode = "return_code" + GrpcRequestCounter = "grpc.server.request_counter" + GrpcRequestCounterDescription = "Grpc request counter" + TotalGrpcRequestCounter = "grpc.server.total_request_counter" + TotalGrpcRequestCounterDescription = "Total grpc request counter" + GrpcStatusCodeCounter = "grpc.server.grpc_status_code" + GrpcStatusCodeCounterDescription = "Grpc status code counter" +) + +func MetricsHandler(metricTypes []metrics.MetricType, ignoredMethodSuffixes ...string) grpc.UnaryServerInterceptor { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return RegisterMetrics(ctx, req, info, handler, metricTypes, ignoredMethodSuffixes...) + } +} + +func RegisterMetrics(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, metricTypes []metrics.MetricType, ignoredMethodSuffixes ...string) (_ interface{}, err error) { + if len(metricTypes) == 0 { + return handler(ctx, req) + } + + for _, ignore := range ignoredMethodSuffixes { + if strings.HasSuffix(info.FullMethod, ignore) { + return handler(ctx, req) + } + } + + resp, err := handler(ctx, req) + if containsMetricsMethod(metrics.MetricTypeRequestCount, metricTypes) { + RegisterGrpcRequestCounter(ctx, info) + } + if containsMetricsMethod(metrics.MetricTypeTotalCount, metricTypes) { + RegisterGrpcTotalRequestCounter(ctx) + } + if containsMetricsMethod(metrics.MetricTypeStatusCode, metricTypes) { + RegisterGrpcRequestCodeCounter(ctx, info, err) + } + return resp, err +} + +func RegisterGrpcRequestCounter(ctx context.Context, info *grpc.UnaryServerInfo) { + var labels = map[string]interface{}{ + GrpcMethod: info.FullMethod, + } + metrics.RegisterCounter(GrpcRequestCounter, GrpcRequestCounterDescription) + metrics.AddCount(ctx, GrpcRequestCounter, 1, labels) +} + +func RegisterGrpcTotalRequestCounter(ctx context.Context) { + metrics.RegisterCounter(TotalGrpcRequestCounter, TotalGrpcRequestCounterDescription) + metrics.AddCount(ctx, TotalGrpcRequestCounter, 1, nil) +} + +func RegisterGrpcRequestCodeCounter(ctx context.Context, info *grpc.UnaryServerInfo, err error) { + statusCode := status.Code(err) + var labels = map[string]interface{}{ + GrpcMethod: info.FullMethod, + ReturnCode: runtime.HTTPStatusFromCode(statusCode), + } + metrics.RegisterCounter(GrpcStatusCodeCounter, GrpcStatusCodeCounterDescription) + metrics.AddCount(ctx, GrpcStatusCodeCounter, 1, labels) +} + +func containsMetricsMethod(metricType metrics.MetricType, metricTypes []metrics.MetricType) bool { + for _, m := range metricTypes { + if m == metricType { + return true + } + } + return false +} diff --git a/internal/api/grpc/server/probes.go b/internal/api/grpc/server/probes.go index 434c07a1bf..e794a44655 100644 --- a/internal/api/grpc/server/probes.go +++ b/internal/api/grpc/server/probes.go @@ -9,7 +9,7 @@ import ( "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/proto" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) type ValidationFunction func(ctx context.Context) error diff --git a/internal/api/grpc/server/server.go b/internal/api/grpc/server/server.go index 57a100247a..4b013646a1 100644 --- a/internal/api/grpc/server/server.go +++ b/internal/api/grpc/server/server.go @@ -2,6 +2,8 @@ package server import ( "context" + grpc_api "github.com/caos/zitadel/internal/api/grpc" + "github.com/caos/zitadel/internal/telemetry/metrics" "github.com/caos/logging" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" @@ -11,7 +13,7 @@ import ( "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/api/grpc/server/middleware" "github.com/caos/zitadel/internal/api/http" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) const ( @@ -27,10 +29,12 @@ type Server interface { } func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, lang language.Tag) *grpc.Server { + metricTypes := []metrics.MetricType{metrics.MetricTypeTotalCount, metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode} return grpc.NewServer( grpc.UnaryInterceptor( grpc_middleware.ChainUnaryServer( middleware.DefaultTracingServer(), + middleware.MetricsHandler(metricTypes, grpc_api.Probes...), middleware.ErrorHandler(), middleware.AuthorizationInterceptor(verifier, authConfig), middleware.TranslationHandler(lang), diff --git a/internal/api/http/middleware/metrics_interceptor.go b/internal/api/http/middleware/metrics_interceptor.go new file mode 100644 index 0000000000..a47f5b32ab --- /dev/null +++ b/internal/api/http/middleware/metrics_interceptor.go @@ -0,0 +1,19 @@ +package middleware + +import ( + "github.com/caos/zitadel/internal/telemetry/metrics" + "net/http" + + http_utils "github.com/caos/zitadel/internal/api/http" +) + +func DefaultMetricsHandler(handler http.Handler) http.Handler { + metricTypes := []metrics.MetricType{metrics.MetricTypeTotalCount} + return MetricsHandler(metricTypes, http_utils.Probes...)(handler) +} + +func MetricsHandler(metricTypes []metrics.MetricType, ignoredMethods ...string) func(http.Handler) http.Handler { + return func(handler http.Handler) http.Handler { + return metrics.NewMetricsHandler(handler, metricTypes, ignoredMethods...) + } +} diff --git a/internal/api/http/middleware/telemetry_interceptor.go b/internal/api/http/middleware/telemetry_interceptor.go new file mode 100644 index 0000000000..bc447c0a1d --- /dev/null +++ b/internal/api/http/middleware/telemetry_interceptor.go @@ -0,0 +1,18 @@ +package middleware + +import ( + "github.com/caos/zitadel/internal/telemetry" + "net/http" + + http_utils "github.com/caos/zitadel/internal/api/http" +) + +func DefaultTelemetryHandler(handler http.Handler) http.Handler { + return TelemetryHandler(http_utils.Probes...)(handler) +} + +func TelemetryHandler(ignoredMethods ...string) func(http.Handler) http.Handler { + return func(handler http.Handler) http.Handler { + return telemetry.TelemetryHandler(handler, ignoredMethods...) + } +} diff --git a/internal/api/http/middleware/trace_interceptor.go b/internal/api/http/middleware/trace_interceptor.go deleted file mode 100644 index af800c95ff..0000000000 --- a/internal/api/http/middleware/trace_interceptor.go +++ /dev/null @@ -1,18 +0,0 @@ -package middleware - -import ( - "net/http" - - http_utils "github.com/caos/zitadel/internal/api/http" - "github.com/caos/zitadel/internal/tracing" -) - -func DefaultTraceHandler(handler http.Handler) http.Handler { - return TraceHandler(http_utils.Probes...)(handler) -} - -func TraceHandler(ignoredMethods ...string) func(http.Handler) http.Handler { - return func(handler http.Handler) http.Handler { - return tracing.TraceHandler(handler, ignoredMethods...) - } -} diff --git a/internal/api/http/server.go b/internal/api/http/server.go index f663b2acd0..489fcc7ec9 100644 --- a/internal/api/http/server.go +++ b/internal/api/http/server.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/caos/logging" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) func Serve(ctx context.Context, handler http.Handler, port, servername string) { diff --git a/internal/api/oidc/auth_request.go b/internal/api/oidc/auth_request.go index 07e2f497b0..e1c57c64b5 100644 --- a/internal/api/oidc/auth_request.go +++ b/internal/api/oidc/auth_request.go @@ -13,7 +13,7 @@ import ( "github.com/caos/zitadel/internal/api/http/middleware" "github.com/caos/zitadel/internal/errors" proj_model "github.com/caos/zitadel/internal/project/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" grant_model "github.com/caos/zitadel/internal/usergrant/model" ) diff --git a/internal/api/oidc/client.go b/internal/api/oidc/client.go index a59176b66a..760c8a007d 100644 --- a/internal/api/oidc/client.go +++ b/internal/api/oidc/client.go @@ -16,7 +16,7 @@ import ( "github.com/caos/zitadel/internal/crypto" "github.com/caos/zitadel/internal/errors" proj_model "github.com/caos/zitadel/internal/project/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" user_model "github.com/caos/zitadel/internal/user/model" grant_model "github.com/caos/zitadel/internal/usergrant/model" ) diff --git a/internal/api/oidc/op.go b/internal/api/oidc/op.go index d3ba142264..f5a11012bf 100644 --- a/internal/api/oidc/op.go +++ b/internal/api/oidc/op.go @@ -2,6 +2,7 @@ package oidc import ( "context" + "github.com/caos/zitadel/internal/telemetry/metrics" "time" "github.com/caos/logging" @@ -12,7 +13,7 @@ import ( "github.com/caos/zitadel/internal/auth/repository" "github.com/caos/zitadel/internal/config/types" "github.com/caos/zitadel/internal/id" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) type OPHandlerConfig struct { @@ -55,12 +56,14 @@ func NewProvider(ctx context.Context, config OPHandlerConfig, repo repository.Re cookieHandler, err := middleware.NewUserAgentHandler(config.UserAgentCookieConfig, id.SonyFlakeGenerator, localDevMode) logging.Log("OIDC-sd4fd").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Panic("cannot user agent handler") config.OPConfig.CodeMethodS256 = true + metricTypes := []metrics.MetricType{metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode, metrics.MetricTypeTotalCount} provider, err := op.NewOpenIDProvider( ctx, config.OPConfig, newStorage(config.StorageConfig, repo), op.WithHttpInterceptors( - middleware.TraceHandler(), + middleware.MetricsHandler(metricTypes), + middleware.TelemetryHandler(), middleware.NoCacheInterceptor, cookieHandler, http_utils.CopyHeadersToContext, diff --git a/internal/auth/repository/eventsourcing/eventstore/auth_request.go b/internal/auth/repository/eventsourcing/eventstore/auth_request.go index 22e1d73d39..f243000410 100644 --- a/internal/auth/repository/eventsourcing/eventstore/auth_request.go +++ b/internal/auth/repository/eventsourcing/eventstore/auth_request.go @@ -21,7 +21,7 @@ import ( org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing" org_view_model "github.com/caos/zitadel/internal/org/repository/view/model" project_view_model "github.com/caos/zitadel/internal/project/repository/view/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" user_model "github.com/caos/zitadel/internal/user/model" user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing" es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" diff --git a/internal/auth/repository/eventsourcing/eventstore/org.go b/internal/auth/repository/eventsourcing/eventstore/org.go index f521a00a77..c5f3ecced0 100644 --- a/internal/auth/repository/eventsourcing/eventstore/org.go +++ b/internal/auth/repository/eventsourcing/eventstore/org.go @@ -9,7 +9,7 @@ import ( "github.com/caos/zitadel/internal/errors" iam_model "github.com/caos/zitadel/internal/iam/model" iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" auth_model "github.com/caos/zitadel/internal/auth/model" auth_view "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view" @@ -50,7 +50,7 @@ func (repo *OrgRepository) SearchOrgs(ctx context.Context, request *org_model.Or } if err == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } diff --git a/internal/auth/repository/eventsourcing/eventstore/token.go b/internal/auth/repository/eventsourcing/eventstore/token.go index 0d7d378bc8..ec3e81aa7b 100644 --- a/internal/auth/repository/eventsourcing/eventstore/token.go +++ b/internal/auth/repository/eventsourcing/eventstore/token.go @@ -3,17 +3,18 @@ package eventstore import ( "context" "strings" - "time" "github.com/caos/logging" - "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view" auth_req_model "github.com/caos/zitadel/internal/auth_request/model" "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/models" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" usr_model "github.com/caos/zitadel/internal/user/model" user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing" "github.com/caos/zitadel/internal/user/repository/view/model" + "time" + + "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view" ) type TokenRepo struct { diff --git a/internal/auth/repository/eventsourcing/eventstore/user.go b/internal/auth/repository/eventsourcing/eventstore/user.go index 9541625986..e5b473c85d 100644 --- a/internal/auth/repository/eventsourcing/eventstore/user.go +++ b/internal/auth/repository/eventsourcing/eventstore/user.go @@ -16,7 +16,7 @@ import ( "github.com/caos/zitadel/internal/eventstore/sdk" org_model "github.com/caos/zitadel/internal/org/model" org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" "github.com/caos/zitadel/internal/user/model" user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing" usr_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" @@ -124,7 +124,7 @@ func (repo *UserRepo) SearchMyExternalIDPs(ctx context.Context, request *model.E } if seqErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } diff --git a/internal/auth/repository/eventsourcing/eventstore/user_grant.go b/internal/auth/repository/eventsourcing/eventstore/user_grant.go index 038d0f0a53..cba39e4314 100644 --- a/internal/auth/repository/eventsourcing/eventstore/user_grant.go +++ b/internal/auth/repository/eventsourcing/eventstore/user_grant.go @@ -12,7 +12,7 @@ import ( global_model "github.com/caos/zitadel/internal/model" org_model "github.com/caos/zitadel/internal/org/model" org_view_model "github.com/caos/zitadel/internal/org/repository/view/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" user_model "github.com/caos/zitadel/internal/user/model" user_view_model "github.com/caos/zitadel/internal/user/repository/view/model" grant_model "github.com/caos/zitadel/internal/usergrant/model" @@ -44,7 +44,7 @@ func (repo *UserGrantRepo) SearchMyUserGrants(ctx context.Context, request *gran } if err == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } diff --git a/internal/auth/repository/eventsourcing/eventstore/user_session.go b/internal/auth/repository/eventsourcing/eventstore/user_session.go index e3a8b53f6b..28246193c3 100644 --- a/internal/auth/repository/eventsourcing/eventstore/user_session.go +++ b/internal/auth/repository/eventsourcing/eventstore/user_session.go @@ -20,3 +20,8 @@ func (repo *UserSessionRepo) GetMyUserSessions(ctx context.Context) ([]*usr_mode } return model.UserSessionsToModel(userSessions), nil } + +func (repo *UserSessionRepo) ActiveUserSessionCount() int64 { + userSessions, _ := repo.View.ActiveUserSessions() + return int64(len(userSessions)) +} diff --git a/internal/auth/repository/eventsourcing/handler/application.go b/internal/auth/repository/eventsourcing/handler/application.go index eccd0d36ab..377e0b0499 100644 --- a/internal/auth/repository/eventsourcing/handler/application.go +++ b/internal/auth/repository/eventsourcing/handler/application.go @@ -22,12 +22,12 @@ const ( applicationTable = "auth.applications" ) -func (p *Application) ViewModel() string { +func (a *Application) ViewModel() string { return applicationTable } -func (p *Application) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestApplicationSequence() +func (a *Application) EventQuery() (*models.SearchQuery, error) { + sequence, err := a.view.GetLatestApplicationSequence() if err != nil { return nil, err } @@ -65,33 +65,37 @@ func (a *Application) Reduce(event *models.Event) (err error) { if err != nil { return err } - return a.view.DeleteApplication(app.ID, event.Sequence) + return a.view.DeleteApplication(app.ID, event.Sequence, event.CreationDate) case es_model.ProjectChanged: apps, err := a.view.ApplicationsByProjectID(event.AggregateID) if err != nil { return err } if len(apps) == 0 { - return a.view.ProcessedApplicationSequence(event.Sequence) + return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) } for _, app := range apps { if err := app.AppendEvent(event); err != nil { return err } } - return a.view.PutApplications(apps, event.Sequence) + return a.view.PutApplications(apps, event.Sequence, event.CreationDate) case es_model.ProjectRemoved: return a.view.DeleteApplicationsByProjectID(event.AggregateID) default: - return a.view.ProcessedApplicationSequence(event.Sequence) + return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return a.view.PutApplication(app) + return a.view.PutApplication(app, event.CreationDate) } -func (p *Application) OnError(event *models.Event, spoolerError error) error { +func (a *Application) OnError(event *models.Event, spoolerError error) error { logging.LogWithFields("SPOOL-ls9ew", "id", event.AggregateID).WithError(spoolerError).Warn("something went wrong in project app handler") - return spooler.HandleError(event, spoolerError, p.view.GetLatestApplicationFailedEvent, p.view.ProcessedApplicationFailedEvent, p.view.ProcessedApplicationSequence, p.errorCountUntilSkip) + return spooler.HandleError(event, spoolerError, a.view.GetLatestApplicationFailedEvent, a.view.ProcessedApplicationFailedEvent, a.view.ProcessedApplicationSequence, a.errorCountUntilSkip) +} + +func (a *Application) OnSuccess() error { + return spooler.HandleSuccess(a.view.UpdateApplicationSpoolerRunTimestamp) } diff --git a/internal/auth/repository/eventsourcing/handler/idp_config.go b/internal/auth/repository/eventsourcing/handler/idp_config.go index 0460b32a9b..e6c21a6260 100644 --- a/internal/auth/repository/eventsourcing/handler/idp_config.go +++ b/internal/auth/repository/eventsourcing/handler/idp_config.go @@ -19,12 +19,12 @@ const ( idpConfigTable = "auth.idp_configs" ) -func (m *IDPConfig) ViewModel() string { +func (i *IDPConfig) ViewModel() string { return idpConfigTable } -func (m *IDPConfig) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestIDPConfigSequence() +func (i *IDPConfig) EventQuery() (*models.SearchQuery, error) { + sequence, err := i.view.GetLatestIDPConfigSequence() if err != nil { return nil, err } @@ -33,17 +33,17 @@ func (m *IDPConfig) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *IDPConfig) Reduce(event *models.Event) (err error) { +func (i *IDPConfig) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate: - err = m.processIdpConfig(iam_model.IDPProviderTypeOrg, event) + err = i.processIdpConfig(iam_model.IDPProviderTypeOrg, event) case iam_es_model.IAMAggregate: - err = m.processIdpConfig(iam_model.IDPProviderTypeSystem, event) + err = i.processIdpConfig(iam_model.IDPProviderTypeSystem, event) } return err } -func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, event *models.Event) (err error) { +func (i *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, event *models.Event) (err error) { idp := new(iam_view_model.IDPConfigView) switch event.Type { case model.IDPConfigAdded, @@ -56,7 +56,7 @@ func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, eve if err != nil { return err } - idp, err = m.view.IDPConfigByID(idp.IDPConfigID) + idp, err = i.view.IDPConfigByID(idp.IDPConfigID) if err != nil { return err } @@ -66,17 +66,21 @@ func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, eve if err != nil { return err } - return m.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence) + return i.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedIDPConfigSequence(event.Sequence) + return i.view.ProcessedIDPConfigSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutIDPConfig(idp, idp.Sequence) + return i.view.PutIDPConfig(idp, idp.Sequence, event.CreationDate) } -func (m *IDPConfig) OnError(event *models.Event, err error) error { +func (i *IDPConfig) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Ejf8s", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp config handler") - return spooler.HandleError(event, err, m.view.GetLatestIDPConfigFailedEvent, m.view.ProcessedIDPConfigFailedEvent, m.view.ProcessedIDPConfigSequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, i.view.GetLatestIDPConfigFailedEvent, i.view.ProcessedIDPConfigFailedEvent, i.view.ProcessedIDPConfigSequence, i.errorCountUntilSkip) +} + +func (i *IDPConfig) OnSuccess() error { + return spooler.HandleSuccess(i.view.UpdateIDPConfigSpoolerRunTimestamp) } diff --git a/internal/auth/repository/eventsourcing/handler/idp_providers.go b/internal/auth/repository/eventsourcing/handler/idp_providers.go index b4c54a2834..b92a20a3b4 100644 --- a/internal/auth/repository/eventsourcing/handler/idp_providers.go +++ b/internal/auth/repository/eventsourcing/handler/idp_providers.go @@ -27,12 +27,12 @@ const ( idpProviderTable = "auth.idp_providers" ) -func (m *IDPProvider) ViewModel() string { +func (i *IDPProvider) ViewModel() string { return idpProviderTable } -func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestIDPProviderSequence() +func (i *IDPProvider) EventQuery() (*models.SearchQuery, error) { + sequence, err := i.view.GetLatestIDPProviderSequence() if err != nil { return nil, err } @@ -41,15 +41,15 @@ func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *IDPProvider) Reduce(event *models.Event) (err error) { +func (i *IDPProvider) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate, org_es_model.OrgAggregate: - err = m.processIdpProvider(event) + err = i.processIdpProvider(event) } return err } -func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { +func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) { provider := new(iam_view_model.IDPProviderView) switch event.Type { case model.LoginPolicyIDPProviderAdded, org_es_model.LoginPolicyIDPProviderAdded: @@ -57,71 +57,75 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { if err != nil { return err } - err = m.fillData(provider) + err = i.fillData(provider) case model.LoginPolicyIDPProviderRemoved, model.LoginPolicyIDPProviderCascadeRemoved, org_es_model.LoginPolicyIDPProviderRemoved, org_es_model.LoginPolicyIDPProviderCascadeRemoved: err = provider.SetData(event) if err != nil { return err } - return m.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence) + return i.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence, event.CreationDate) case model.IDPConfigChanged, org_es_model.IDPConfigChanged: esConfig := new(iam_view_model.IDPConfigView) providerType := iam_model.IDPProviderTypeSystem - if event.AggregateID != m.systemDefaults.IamID { + if event.AggregateID != i.systemDefaults.IamID { providerType = iam_model.IDPProviderTypeOrg } esConfig.AppendEvent(providerType, event) - providers, err := m.view.IDPProvidersByIDPConfigID(esConfig.IDPConfigID) + providers, err := i.view.IDPProvidersByIDPConfigID(esConfig.IDPConfigID) if err != nil { return err } config := new(iam_model.IDPConfig) - if event.AggregateID == m.systemDefaults.IamID { - config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID) + if event.AggregateID == i.systemDefaults.IamID { + config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID) } else { - config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID) + config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID) } if err != nil { return err } for _, provider := range providers { - m.fillConfigData(provider, config) + i.fillConfigData(provider, config) } - return m.view.PutIDPProviders(event.Sequence, providers...) + return i.view.PutIDPProviders(event.Sequence, event.CreationDate, providers...) case org_es_model.LoginPolicyRemoved: - return m.view.DeleteIDPProvidersByAggregateID(event.AggregateID, event.Sequence) + return i.view.DeleteIDPProvidersByAggregateID(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedIDPProviderSequence(event.Sequence) + return i.view.ProcessedIDPProviderSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutIDPProvider(provider, provider.Sequence) + return i.view.PutIDPProvider(provider, provider.Sequence, event.CreationDate) } -func (m *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) { +func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) { var config *iam_model.IDPConfig if provider.IDPProviderType == int32(iam_model.IDPProviderTypeSystem) { - config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, provider.IDPConfigID) + config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, provider.IDPConfigID) } else { - config, err = m.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID) + config, err = i.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID) } if err != nil { return err } - m.fillConfigData(provider, config) + i.fillConfigData(provider, config) return nil } -func (m *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *iam_model.IDPConfig) { +func (i *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *iam_model.IDPConfig) { provider.Name = config.Name provider.StylingType = int32(config.StylingType) provider.IDPConfigType = int32(config.Type) provider.IDPState = int32(config.State) } -func (m *IDPProvider) OnError(event *models.Event, err error) error { +func (i *IDPProvider) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Fjd89", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler") - return spooler.HandleError(event, err, m.view.GetLatestIDPProviderFailedEvent, m.view.ProcessedIDPProviderFailedEvent, m.view.ProcessedIDPProviderSequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, i.view.GetLatestIDPProviderFailedEvent, i.view.ProcessedIDPProviderFailedEvent, i.view.ProcessedIDPProviderSequence, i.errorCountUntilSkip) +} + +func (i *IDPProvider) OnSuccess() error { + return spooler.HandleSuccess(i.view.UpdateIDPProviderSpoolerRunTimestamp) } diff --git a/internal/auth/repository/eventsourcing/handler/key.go b/internal/auth/repository/eventsourcing/handler/key.go index e56e20d153..48f224cc29 100644 --- a/internal/auth/repository/eventsourcing/handler/key.go +++ b/internal/auth/repository/eventsourcing/handler/key.go @@ -41,11 +41,11 @@ func (k *Key) Reduce(event *models.Event) error { return err } if privateKey.Expiry.Before(time.Now()) && publicKey.Expiry.Before(time.Now()) { - return k.view.ProcessedKeySequence(event.Sequence) + return k.view.ProcessedKeySequence(event.Sequence, event.CreationDate) } - return k.view.PutKeys(privateKey, publicKey, event.Sequence) + return k.view.PutKeys(privateKey, publicKey, event.Sequence, event.CreationDate) default: - return k.view.ProcessedKeySequence(event.Sequence) + return k.view.ProcessedKeySequence(event.Sequence, event.CreationDate) } } @@ -53,3 +53,9 @@ func (k *Key) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-GHa3a", "id", event.AggregateID).WithError(err).Warn("something went wrong in key handler") return spooler.HandleError(event, err, k.view.GetLatestKeyFailedEvent, k.view.ProcessedKeyFailedEvent, k.view.ProcessedKeySequence, k.errorCountUntilSkip) } + +func (k *Key) OnSuccess() error { + err := spooler.HandleSuccess(k.view.UpdateKeySpoolerRunTimestamp) + logging.LogWithFields("SPOOL-vM9sd", "table", keyTable).OnError(err).Warn("could not process on success func") + return err +} diff --git a/internal/auth/repository/eventsourcing/handler/login_policy.go b/internal/auth/repository/eventsourcing/handler/login_policy.go index ca01a1ea76..b92dd17a9e 100644 --- a/internal/auth/repository/eventsourcing/handler/login_policy.go +++ b/internal/auth/repository/eventsourcing/handler/login_policy.go @@ -19,12 +19,12 @@ const ( loginPolicyTable = "auth.login_policies" ) -func (m *LoginPolicy) ViewModel() string { +func (p *LoginPolicy) ViewModel() string { return loginPolicyTable } -func (m *LoginPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestLoginPolicySequence() +func (p *LoginPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestLoginPolicySequence() if err != nil { return nil, err } @@ -33,15 +33,15 @@ func (m *LoginPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *LoginPolicy) Reduce(event *models.Event) (err error) { +func (p *LoginPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: - err = m.processLoginPolicy(event) + err = p.processLoginPolicy(event) } return err } -func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { +func (p *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { policy := new(iam_model.LoginPolicyView) switch event.Type { case iam_es_model.LoginPolicyAdded, model.LoginPolicyAdded: @@ -51,23 +51,27 @@ func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { iam_es_model.LoginPolicySecondFactorRemoved, model.LoginPolicySecondFactorRemoved, iam_es_model.LoginPolicyMultiFactorAdded, model.LoginPolicyMultiFactorAdded, iam_es_model.LoginPolicyMultiFactorRemoved, model.LoginPolicyMultiFactorRemoved: - policy, err = m.view.LoginPolicyByAggregateID(event.AggregateID) + policy, err = p.view.LoginPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) case model.LoginPolicyRemoved: - return m.view.DeleteLoginPolicy(event.AggregateID, event.Sequence) + return p.view.DeleteLoginPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedLoginPolicySequence(event.Sequence) + return p.view.ProcessedLoginPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutLoginPolicy(policy, policy.Sequence) + return p.view.PutLoginPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *LoginPolicy) OnError(event *models.Event, err error) error { +func (p *LoginPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-5id9s", "id", event.AggregateID).WithError(err).Warn("something went wrong in login policy handler") - return spooler.HandleError(event, err, m.view.GetLatestLoginPolicyFailedEvent, m.view.ProcessedLoginPolicyFailedEvent, m.view.ProcessedLoginPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestLoginPolicyFailedEvent, p.view.ProcessedLoginPolicyFailedEvent, p.view.ProcessedLoginPolicySequence, p.errorCountUntilSkip) +} + +func (p *LoginPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateLoginPolicySpoolerRunTimestamp) } diff --git a/internal/auth/repository/eventsourcing/handler/machine_keys.go b/internal/auth/repository/eventsourcing/handler/machine_keys.go index 84513ae0fa..f9af7e86fb 100644 --- a/internal/auth/repository/eventsourcing/handler/machine_keys.go +++ b/internal/auth/repository/eventsourcing/handler/machine_keys.go @@ -48,26 +48,30 @@ func (d *MachineKeys) processMachineKeys(event *models.Event) (err error) { case model.MachineKeyAdded: err = key.AppendEvent(event) if key.ExpirationDate.Before(time.Now()) { - return d.view.ProcessedMachineKeySequence(event.Sequence) + return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate) } case model.MachineKeyRemoved: err = key.SetData(event) if err != nil { return err } - return d.view.DeleteMachineKey(key.ID, event.Sequence) + return d.view.DeleteMachineKey(key.ID, event.Sequence, event.CreationDate) case model.UserRemoved: - return d.view.DeleteMachineKeysByUserID(event.AggregateID, event.Sequence) + return d.view.DeleteMachineKeysByUserID(event.AggregateID, event.Sequence, event.CreationDate) default: - return d.view.ProcessedMachineKeySequence(event.Sequence) + return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return d.view.PutMachineKey(key, key.Sequence) + return d.view.PutMachineKey(key, key.Sequence, event.CreationDate) } func (d *MachineKeys) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-S9fe", "id", event.AggregateID).WithError(err).Warn("something went wrong in machine key handler") return spooler.HandleError(event, err, d.view.GetLatestMachineKeyFailedEvent, d.view.ProcessedMachineKeyFailedEvent, d.view.ProcessedMachineKeySequence, d.errorCountUntilSkip) } + +func (d *MachineKeys) OnSuccess() error { + return spooler.HandleSuccess(d.view.UpdateMachineKeySpoolerRunTimestamp) +} diff --git a/internal/auth/repository/eventsourcing/handler/org.go b/internal/auth/repository/eventsourcing/handler/org.go index 58bafb6ac0..909cfefc4a 100644 --- a/internal/auth/repository/eventsourcing/handler/org.go +++ b/internal/auth/repository/eventsourcing/handler/org.go @@ -58,16 +58,20 @@ func (o *Org) Reduce(event *es_models.Event) (err error) { } org.Domain = domain.Domain default: - return o.view.ProcessedOrgSequence(event.Sequence) + return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return o.view.PutOrg(org) + return o.view.PutOrg(org, event.CreationDate) } func (o *Org) OnError(event *es_models.Event, spoolerErr error) error { logging.LogWithFields("SPOOL-8siWS", "id", event.AggregateID).WithError(spoolerErr).Warn("something went wrong in org handler") return spooler.HandleError(event, spoolerErr, o.view.GetLatestOrgFailedEvent, o.view.ProcessedOrgFailedEvent, o.view.ProcessedOrgSequence, o.errorCountUntilSkip) } + +func (o *Org) OnSuccess() error { + return spooler.HandleSuccess(o.view.UpdateOrgSpoolerRunTimestamp) +} diff --git a/internal/auth/repository/eventsourcing/handler/org_iam_policy.go b/internal/auth/repository/eventsourcing/handler/org_iam_policy.go index 55f72f74d7..ac28b5c7c4 100644 --- a/internal/auth/repository/eventsourcing/handler/org_iam_policy.go +++ b/internal/auth/repository/eventsourcing/handler/org_iam_policy.go @@ -19,12 +19,12 @@ const ( orgIAMPolicyTable = "auth.org_iam_policies" ) -func (m *OrgIAMPolicy) ViewModel() string { +func (p *OrgIAMPolicy) ViewModel() string { return orgIAMPolicyTable } -func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestOrgIAMPolicySequence() +func (p *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestOrgIAMPolicySequence() if err != nil { return nil, err } @@ -33,37 +33,41 @@ func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *OrgIAMPolicy) Reduce(event *models.Event) (err error) { +func (p *OrgIAMPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: - err = m.processOrgIAMPolicy(event) + err = p.processOrgIAMPolicy(event) } return err } -func (m *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) { +func (p *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) { policy := new(iam_model.OrgIAMPolicyView) switch event.Type { case iam_es_model.OrgIAMPolicyAdded, model.OrgIAMPolicyAdded: err = policy.AppendEvent(event) case iam_es_model.OrgIAMPolicyChanged, model.OrgIAMPolicyChanged: - policy, err = m.view.OrgIAMPolicyByAggregateID(event.AggregateID) + policy, err = p.view.OrgIAMPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) case model.OrgIAMPolicyRemoved: - return m.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence) + return p.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedOrgIAMPolicySequence(event.Sequence) + return p.view.ProcessedOrgIAMPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutOrgIAMPolicy(policy, policy.Sequence) + return p.view.PutOrgIAMPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *OrgIAMPolicy) OnError(event *models.Event, err error) error { +func (p *OrgIAMPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-3Gj8s", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgIAM policy handler") - return spooler.HandleError(event, err, m.view.GetLatestOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicySequence, p.errorCountUntilSkip) +} + +func (p *OrgIAMPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateOrgIAMPolicySpoolerRunTimestamp) } diff --git a/internal/auth/repository/eventsourcing/handler/password_complexity_policy.go b/internal/auth/repository/eventsourcing/handler/password_complexity_policy.go index c280615988..d3656a164a 100644 --- a/internal/auth/repository/eventsourcing/handler/password_complexity_policy.go +++ b/internal/auth/repository/eventsourcing/handler/password_complexity_policy.go @@ -19,12 +19,12 @@ const ( passwordComplexityPolicyTable = "auth.password_complexity_policies" ) -func (m *PasswordComplexityPolicy) ViewModel() string { +func (p *PasswordComplexityPolicy) ViewModel() string { return passwordComplexityPolicyTable } -func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestPasswordComplexityPolicySequence() +func (p *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestPasswordComplexityPolicySequence() if err != nil { return nil, err } @@ -33,37 +33,41 @@ func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) { +func (p *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: - err = m.processPasswordComplexityPolicy(event) + err = p.processPasswordComplexityPolicy(event) } return err } -func (m *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) { +func (p *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) { policy := new(iam_model.PasswordComplexityPolicyView) switch event.Type { case iam_es_model.PasswordComplexityPolicyAdded, model.PasswordComplexityPolicyAdded: err = policy.AppendEvent(event) case iam_es_model.PasswordComplexityPolicyChanged, model.PasswordComplexityPolicyChanged: - policy, err = m.view.PasswordComplexityPolicyByAggregateID(event.AggregateID) + policy, err = p.view.PasswordComplexityPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) case model.PasswordComplexityPolicyRemoved: - return m.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence) + return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedPasswordComplexityPolicySequence(event.Sequence) + return p.view.ProcessedPasswordComplexityPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutPasswordComplexityPolicy(policy, policy.Sequence) + return p.view.PutPasswordComplexityPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *PasswordComplexityPolicy) OnError(event *models.Event, err error) error { +func (p *PasswordComplexityPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordComplexity policy handler") - return spooler.HandleError(event, err, m.view.GetLatestPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicySequence, p.errorCountUntilSkip) +} + +func (p *PasswordComplexityPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdatePasswordComplexityPolicySpoolerRunTimestamp) } diff --git a/internal/auth/repository/eventsourcing/handler/project_role.go b/internal/auth/repository/eventsourcing/handler/project_role.go index e877c867a4..c469019b9f 100644 --- a/internal/auth/repository/eventsourcing/handler/project_role.go +++ b/internal/auth/repository/eventsourcing/handler/project_role.go @@ -52,19 +52,23 @@ func (p *ProjectRole) Reduce(event *models.Event) (err error) { if err != nil { return err } - return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event.Sequence) + return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event.Sequence, event.CreationDate) case es_model.ProjectRemoved: return p.view.DeleteProjectRolesByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectRoleSequence(event.Sequence) + return p.view.ProcessedProjectRoleSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return p.view.PutProjectRole(role) + return p.view.PutProjectRole(role, event.CreationDate) } func (p *ProjectRole) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-lso9w", "id", event.AggregateID).WithError(err).Warn("something went wrong in project role handler") return spooler.HandleError(event, err, p.view.GetLatestProjectRoleFailedEvent, p.view.ProcessedProjectRoleFailedEvent, p.view.ProcessedProjectRoleSequence, p.errorCountUntilSkip) } + +func (p *ProjectRole) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateProjectRoleSpoolerRunTimestamp) +} diff --git a/internal/auth/repository/eventsourcing/handler/token.go b/internal/auth/repository/eventsourcing/handler/token.go index 8fb4c65739..2c056cc064 100644 --- a/internal/auth/repository/eventsourcing/handler/token.go +++ b/internal/auth/repository/eventsourcing/handler/token.go @@ -49,7 +49,7 @@ func (t *Token) Reduce(event *models.Event) (err error) { if err != nil { return err } - return t.view.PutToken(token) + return t.view.PutToken(token, event.CreationDate) case user_es_model.UserProfileChanged, user_es_model.HumanProfileChanged: user := new(view_model.UserView) @@ -61,25 +61,25 @@ func (t *Token) Reduce(event *models.Event) (err error) { for _, token := range tokens { token.PreferredLanguage = user.PreferredLanguage } - return t.view.PutTokens(tokens, event.Sequence) + return t.view.PutTokens(tokens, event.Sequence, event.CreationDate) case user_es_model.SignedOut, user_es_model.HumanSignedOut: id, err := agentIDFromSession(event) if err != nil { return err } - return t.view.DeleteSessionTokens(id, event.AggregateID, event.Sequence) + return t.view.DeleteSessionTokens(id, event.AggregateID, event.Sequence, event.CreationDate) case user_es_model.UserLocked, user_es_model.UserDeactivated, user_es_model.UserRemoved: - return t.view.DeleteUserTokens(event.AggregateID, event.Sequence) + return t.view.DeleteUserTokens(event.AggregateID, event.Sequence, event.CreationDate) case project_es_model.ApplicationDeactivated, project_es_model.ApplicationRemoved: application, err := applicationFromSession(event) if err != nil { return err } - return t.view.DeleteApplicationTokens(event.Sequence, application.AppID) + return t.view.DeleteApplicationTokens(event.Sequence, event.CreationDate, application.AppID) case project_es_model.ProjectDeactivated, project_es_model.ProjectRemoved: project, err := t.ProjectEvents.ProjectByID(context.Background(), event.AggregateID) @@ -90,9 +90,9 @@ func (t *Token) Reduce(event *models.Event) (err error) { for _, app := range project.Applications { applicationsIDs = append(applicationsIDs, app.AppID) } - return t.view.DeleteApplicationTokens(event.Sequence, applicationsIDs...) + return t.view.DeleteApplicationTokens(event.Sequence, event.CreationDate, applicationsIDs...) default: - return t.view.ProcessedTokenSequence(event.Sequence) + return t.view.ProcessedTokenSequence(event.Sequence, event.CreationDate) } } @@ -118,3 +118,7 @@ func applicationFromSession(event *models.Event) (*project_es_model.Application, } return application, nil } + +func (t *Token) OnSuccess() error { + return spooler.HandleSuccess(t.view.UpdateTokenSpoolerRunTimestamp) +} diff --git a/internal/auth/repository/eventsourcing/handler/user.go b/internal/auth/repository/eventsourcing/handler/user.go index c05c2f0f73..5d04b62a3b 100644 --- a/internal/auth/repository/eventsourcing/handler/user.go +++ b/internal/auth/repository/eventsourcing/handler/user.go @@ -114,14 +114,14 @@ func (u *User) ProcessUser(event *models.Event) (err error) { } err = u.fillLoginNames(user) case es_model.UserRemoved: - return u.view.DeleteUser(event.AggregateID, event.Sequence) + return u.view.DeleteUser(event.AggregateID, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserSequence(event.Sequence) + return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return u.view.PutUser(user, user.Sequence) + return u.view.PutUser(user, user.Sequence, event.CreationDate) } func (u *User) fillLoginNames(user *view_model.UserView) (err error) { @@ -152,7 +152,7 @@ func (u *User) ProcessOrg(event *models.Event) (err error) { case org_es_model.OrgDomainPrimarySet: return u.fillPreferredLoginNamesOnOrgUsers(event) default: - return u.view.ProcessedUserSequence(event.Sequence) + return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) } } @@ -175,7 +175,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.SetLoginNames(policy, org.Domains) } - return u.view.PutUsers(users, event.Sequence) + return u.view.PutUsers(users, event.Sequence, event.CreationDate) } func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { @@ -200,10 +200,14 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) } - return u.view.PutUsers(users, 0) + return u.view.PutUsers(users, 0, event.CreationDate) } func (u *User) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-is8aAWima", "id", event.AggregateID).WithError(err).Warn("something went wrong in user handler") return spooler.HandleError(event, err, u.view.GetLatestUserFailedEvent, u.view.ProcessedUserFailedEvent, u.view.ProcessedUserSequence, u.errorCountUntilSkip) } + +func (u *User) OnSuccess() error { + return spooler.HandleSuccess(u.view.UpdateUserSpoolerRunTimestamp) +} diff --git a/internal/auth/repository/eventsourcing/handler/user_external_idps.go b/internal/auth/repository/eventsourcing/handler/user_external_idps.go index 5de4130bcf..826d79170c 100644 --- a/internal/auth/repository/eventsourcing/handler/user_external_idps.go +++ b/internal/auth/repository/eventsourcing/handler/user_external_idps.go @@ -29,12 +29,12 @@ const ( externalIDPTable = "auth.user_external_idps" ) -func (m *ExternalIDP) ViewModel() string { +func (i *ExternalIDP) ViewModel() string { return externalIDPTable } -func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestExternalIDPSequence() +func (i *ExternalIDP) EventQuery() (*models.SearchQuery, error) { + sequence, err := i.view.GetLatestExternalIDPSequence() if err != nil { return nil, err } @@ -43,17 +43,17 @@ func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *ExternalIDP) Reduce(event *models.Event) (err error) { +func (i *ExternalIDP) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.UserAggregate: - err = m.processUser(event) + err = i.processUser(event) case iam_es_model.IAMAggregate, org_es_model.OrgAggregate: - err = m.processIdpConfig(event) + err = i.processIdpConfig(event) } return err } -func (m *ExternalIDP) processUser(event *models.Event) (err error) { +func (i *ExternalIDP) processUser(event *models.Event) (err error) { externalIDP := new(usr_view_model.ExternalIDPView) switch event.Type { case model.HumanExternalIDPAdded: @@ -61,25 +61,25 @@ func (m *ExternalIDP) processUser(event *models.Event) (err error) { if err != nil { return err } - err = m.fillData(externalIDP) + err = i.fillData(externalIDP) case model.HumanExternalIDPRemoved, model.HumanExternalIDPCascadeRemoved: err = externalIDP.SetData(event) if err != nil { return err } - return m.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence) + return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence, event.CreationDate) case model.UserRemoved: - return m.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence) + return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedExternalIDPSequence(event.Sequence) + return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutExternalIDP(externalIDP, externalIDP.Sequence) + return i.view.PutExternalIDP(externalIDP, externalIDP.Sequence, event.CreationDate) } -func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) { +func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) { switch event.Type { case iam_es_model.IDPConfigChanged, org_es_model.IDPConfigChanged: configView := new(iam_view_model.IDPConfigView) @@ -89,45 +89,49 @@ func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) { } else { configView.AppendEvent(iam_model.IDPProviderTypeOrg, event) } - exterinalIDPs, err := m.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID) + exterinalIDPs, err := i.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID) if err != nil { return err } if event.AggregateType == iam_es_model.IAMAggregate { - config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) + config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) } else { - config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) + config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) } if err != nil { return err } for _, provider := range exterinalIDPs { - m.fillConfigData(provider, config) + i.fillConfigData(provider, config) } - return m.view.PutExternalIDPs(event.Sequence, exterinalIDPs...) + return i.view.PutExternalIDPs(event.Sequence, event.CreationDate, exterinalIDPs...) default: - return m.view.ProcessedExternalIDPSequence(event.Sequence) + return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) } return nil } -func (m *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error { - config, err := m.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID) +func (i *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error { + config, err := i.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID) if caos_errs.IsNotFound(err) { - config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, externalIDP.IDPConfigID) + config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, externalIDP.IDPConfigID) } if err != nil { return err } - m.fillConfigData(externalIDP, config) + i.fillConfigData(externalIDP, config) return nil } -func (m *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) { +func (i *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) { externalIDP.IDPName = config.Name } -func (m *ExternalIDP) OnError(event *models.Event, err error) error { +func (i *ExternalIDP) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-4Rsu8", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler") - return spooler.HandleError(event, err, m.view.GetLatestExternalIDPFailedEvent, m.view.ProcessedExternalIDPFailedEvent, m.view.ProcessedExternalIDPSequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, i.view.GetLatestExternalIDPFailedEvent, i.view.ProcessedExternalIDPFailedEvent, i.view.ProcessedExternalIDPSequence, i.errorCountUntilSkip) +} + +func (i *ExternalIDP) OnSuccess() error { + return spooler.HandleSuccess(i.view.UpdateExternalIDPSpoolerRunTimestamp) } diff --git a/internal/auth/repository/eventsourcing/handler/user_grant.go b/internal/auth/repository/eventsourcing/handler/user_grant.go index d9ded99e7f..c61f831162 100644 --- a/internal/auth/repository/eventsourcing/handler/user_grant.go +++ b/internal/auth/repository/eventsourcing/handler/user_grant.go @@ -97,14 +97,14 @@ func (u *UserGrant) processUserGrant(event *models.Event) (err error) { } err = grant.AppendEvent(event) case grant_es_model.UserGrantRemoved, grant_es_model.UserGrantCascadeRemoved: - return u.view.DeleteUserGrant(event.AggregateID, event.Sequence) + return u.view.DeleteUserGrant(event.AggregateID, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return u.view.PutUserGrant(grant, grant.Sequence) + return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate) } func (u *UserGrant) processUser(event *models.Event) (err error) { @@ -119,7 +119,7 @@ func (u *UserGrant) processUser(event *models.Event) (err error) { return err } if len(grants) == 0 { - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } user, err := u.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -128,9 +128,9 @@ func (u *UserGrant) processUser(event *models.Event) (err error) { for _, grant := range grants { u.fillUserData(grant, user) } - return u.view.PutUserGrants(grants, event.Sequence) + return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } } @@ -148,7 +148,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { for _, grant := range grants { u.fillProjectData(grant, project) } - return u.view.PutUserGrants(grants, event.Sequence) + return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate) case proj_es_model.ProjectMemberAdded, proj_es_model.ProjectMemberChanged, proj_es_model.ProjectMemberRemoved: member := new(proj_es_model.ProjectMember) member.SetData(event) @@ -158,7 +158,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { member.SetData(event) return u.processMember(event, "PROJECT_GRANT", member.GrantID, member.UserID, member.Roles) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } } @@ -169,7 +169,7 @@ func (u *UserGrant) processOrg(event *models.Event) (err error) { member.SetData(event) return u.processMember(event, "ORG", "", member.UserID, member.Roles) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } } @@ -207,16 +207,16 @@ func (u *UserGrant) processIAMMember(event *models.Event, rolePrefix string, suf } grant.Sequence = event.Sequence grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, grant.Sequence) + return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate) case iam_es_model.IAMMemberRemoved: member.SetData(event) grant, err := u.view.UserGrantByIDs(u.iamID, u.iamProjectID, member.UserID) if err != nil { return err } - return u.view.DeleteUserGrant(grant.ID, event.Sequence) + return u.view.DeleteUserGrant(grant.ID, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } } @@ -252,7 +252,7 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st } grant.Sequence = event.Sequence grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, event.Sequence) + return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate) case org_es_model.OrgMemberRemoved, proj_es_model.ProjectMemberRemoved, proj_es_model.ProjectGrantMemberRemoved: @@ -262,18 +262,18 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st return err } if errors.IsNotFound(err) { - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } if roleSuffix != "" { roleKeys = suffixRoles(roleSuffix, roleKeys) } if grant.RoleKeys == nil { - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } grant.RoleKeys = mergeExistingRoles(rolePrefix, roleSuffix, grant.RoleKeys, nil) - return u.view.PutUserGrant(grant, event.Sequence) + return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } } @@ -367,3 +367,7 @@ func (u *UserGrant) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-UZmc7", "id", event.AggregateID).WithError(err).Warn("something went wrong in user grant handler") return spooler.HandleError(event, err, u.view.GetLatestUserGrantFailedEvent, u.view.ProcessedUserGrantFailedEvent, u.view.ProcessedUserGrantSequence, u.errorCountUntilSkip) } + +func (u *UserGrant) OnSuccess() error { + return spooler.HandleSuccess(u.view.UpdateUserGrantSpoolerRunTimestamp) +} diff --git a/internal/auth/repository/eventsourcing/handler/user_membership.go b/internal/auth/repository/eventsourcing/handler/user_membership.go index 7a1145d224..7b231a78b5 100644 --- a/internal/auth/repository/eventsourcing/handler/user_membership.go +++ b/internal/auth/repository/eventsourcing/handler/user_membership.go @@ -74,14 +74,14 @@ func (m *UserMembership) processIam(event *models.Event) (err error) { } err = member.AppendEvent(event) case iam_es_model.IAMMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event.Sequence) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event.Sequence, event.CreationDate) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence) + return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence) + return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) } func (m *UserMembership) fillIamDisplayName(member *usr_es_model.UserMembershipView) { @@ -105,16 +105,16 @@ func (m *UserMembership) processOrg(event *models.Event) (err error) { } err = member.AppendEvent(event) case org_es_model.OrgMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence, event.CreationDate) case org_es_model.OrgChanged: return m.updateOrgName(event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence) + return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence) + return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) } func (m *UserMembership) fillOrgName(member *usr_es_model.UserMembershipView) (err error) { @@ -145,7 +145,7 @@ func (m *UserMembership) updateOrgName(event *models.Event) error { membership.DisplayName = org.Name } } - return m.view.BulkPutUserMemberships(memberships, event.Sequence) + return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate) } func (m *UserMembership) processProject(event *models.Event) (err error) { @@ -168,7 +168,7 @@ func (m *UserMembership) processProject(event *models.Event) (err error) { } err = member.AppendEvent(event) case proj_es_model.ProjectMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event.Sequence) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event.Sequence, event.CreationDate) case proj_es_model.ProjectGrantMemberChanged: member, err = m.view.UserMembershipByIDs(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant) if err != nil { @@ -176,20 +176,20 @@ func (m *UserMembership) processProject(event *models.Event) (err error) { } err = member.AppendEvent(event) case proj_es_model.ProjectGrantMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence, event.CreationDate) case proj_es_model.ProjectChanged: return m.updateProjectDisplayName(event) case proj_es_model.ProjectRemoved: - return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event.Sequence) + return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event.Sequence, event.CreationDate) case proj_es_model.ProjectGrantRemoved: - return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event.Sequence) + return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence) + return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence) + return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) } func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembershipView) (err error) { @@ -214,15 +214,15 @@ func (m *UserMembership) updateProjectDisplayName(event *models.Event) error { for _, membership := range memberships { membership.DisplayName = project.Name } - return m.view.BulkPutUserMemberships(memberships, event.Sequence) + return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate) } func (m *UserMembership) processUser(event *models.Event) (err error) { switch event.Type { case model.UserRemoved: - return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event.Sequence) + return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence) + return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) } } @@ -230,3 +230,7 @@ func (m *UserMembership) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Ms3fj", "id", event.AggregateID).WithError(err).Warn("something went wrong in user membership handler") return spooler.HandleError(event, err, m.view.GetLatestUserMembershipFailedEvent, m.view.ProcessedUserMembershipFailedEvent, m.view.ProcessedUserMembershipSequence, m.errorCountUntilSkip) } + +func (m *UserMembership) OnSuccess() error { + return spooler.HandleSuccess(m.view.UpdateUserMembershipSpoolerRunTimestamp) +} diff --git a/internal/auth/repository/eventsourcing/handler/user_session.go b/internal/auth/repository/eventsourcing/handler/user_session.go index 305d5cd04d..3931e62f24 100644 --- a/internal/auth/repository/eventsourcing/handler/user_session.go +++ b/internal/auth/repository/eventsourcing/handler/user_session.go @@ -84,7 +84,7 @@ func (u *UserSession) Reduce(event *models.Event) (err error) { return err } if len(sessions) == 0 { - return u.view.ProcessedUserSessionSequence(event.Sequence) + return u.view.ProcessedUserSessionSequence(event.Sequence, event.CreationDate) } for _, session := range sessions { session.AppendEvent(event) @@ -92,11 +92,11 @@ func (u *UserSession) Reduce(event *models.Event) (err error) { return err } } - return u.view.PutUserSessions(sessions, event.Sequence) + return u.view.PutUserSessions(sessions, event.Sequence, event.CreationDate) case es_model.UserRemoved: - return u.view.DeleteUserSessions(event.AggregateID, event.Sequence) + return u.view.DeleteUserSessions(event.AggregateID, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserSessionSequence(event.Sequence) + return u.view.ProcessedUserSessionSequence(event.Sequence, event.CreationDate) } } @@ -105,12 +105,16 @@ func (u *UserSession) OnError(event *models.Event, err error) error { return spooler.HandleError(event, err, u.view.GetLatestUserSessionFailedEvent, u.view.ProcessedUserSessionFailedEvent, u.view.ProcessedUserSessionSequence, u.errorCountUntilSkip) } +func (u *UserSession) OnSuccess() error { + return spooler.HandleSuccess(u.view.UpdateUserSessionSpoolerRunTimestamp) +} + func (u *UserSession) updateSession(session *view_model.UserSessionView, event *models.Event) error { session.AppendEvent(event) if err := u.fillUserInfo(session, event.AggregateID); err != nil { return err } - return u.view.PutUserSession(session) + return u.view.PutUserSession(session, event.CreationDate) } func (u *UserSession) fillUserInfo(session *view_model.UserSessionView, id string) error { diff --git a/internal/auth/repository/eventsourcing/repository.go b/internal/auth/repository/eventsourcing/repository.go index aa5bbeadea..3647222c44 100644 --- a/internal/auth/repository/eventsourcing/repository.go +++ b/internal/auth/repository/eventsourcing/repository.go @@ -2,7 +2,6 @@ package eventsourcing import ( "context" - "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/auth/repository/eventsourcing/eventstore" "github.com/caos/zitadel/internal/auth/repository/eventsourcing/handler" diff --git a/internal/auth/repository/eventsourcing/view/application.go b/internal/auth/repository/eventsourcing/view/application.go index 06e59881eb..556d31d251 100644 --- a/internal/auth/repository/eventsourcing/view/application.go +++ b/internal/auth/repository/eventsourcing/view/application.go @@ -8,6 +8,7 @@ import ( "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -26,28 +27,28 @@ func (v *View) SearchApplications(request *proj_model.ApplicationSearchRequest) return view.SearchApplications(v.Db, applicationTable, request) } -func (v *View) PutApplication(app *model.ApplicationView) error { +func (v *View) PutApplication(app *model.ApplicationView, eventTimestamp time.Time) error { err := view.PutApplication(v.Db, applicationTable, app) if err != nil { return err } - return v.ProcessedApplicationSequence(app.Sequence) + return v.ProcessedApplicationSequence(app.Sequence, eventTimestamp) } -func (v *View) PutApplications(apps []*model.ApplicationView, sequence uint64) error { +func (v *View) PutApplications(apps []*model.ApplicationView, sequence uint64, eventTimestamp time.Time) error { err := view.PutApplications(v.Db, applicationTable, apps...) if err != nil { return err } - return v.ProcessedApplicationSequence(sequence) + return v.ProcessedApplicationSequence(sequence, eventTimestamp) } -func (v *View) DeleteApplication(appID string, eventSequence uint64) error { +func (v *View) DeleteApplication(appID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteApplication(v.Db, applicationTable, appID) if err != nil { return nil } - return v.ProcessedApplicationSequence(eventSequence) + return v.ProcessedApplicationSequence(eventSequence, eventTimestamp) } func (v *View) DeleteApplicationsByProjectID(projectID string) error { @@ -58,8 +59,12 @@ func (v *View) GetLatestApplicationSequence() (*repository.CurrentSequence, erro return v.latestSequence(applicationTable) } -func (v *View) ProcessedApplicationSequence(eventSequence uint64) error { - return v.saveCurrentSequence(applicationTable, eventSequence) +func (v *View) ProcessedApplicationSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(applicationTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateApplicationSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(applicationTable) } func (v *View) GetLatestApplicationFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/external_idps.go b/internal/auth/repository/eventsourcing/view/external_idps.go index 6050dd73d8..1381611037 100644 --- a/internal/auth/repository/eventsourcing/view/external_idps.go +++ b/internal/auth/repository/eventsourcing/view/external_idps.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -32,44 +33,48 @@ func (v *View) SearchExternalIDPs(request *usr_model.ExternalIDPSearchRequest) ( return view.SearchExternalIDPs(v.Db, externalIDPTable, request) } -func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64) error { +func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64, eventTimestamp time.Time) error { err := view.PutExternalIDP(v.Db, externalIDPTable, externalIDP) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence) + return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) } -func (v *View) PutExternalIDPs(sequence uint64, externalIDPs ...*model.ExternalIDPView) error { +func (v *View) PutExternalIDPs(sequence uint64, eventTimestamp time.Time, externalIDPs ...*model.ExternalIDPView) error { err := view.PutExternalIDPs(v.Db, externalIDPTable, externalIDPs...) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence) + return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) } -func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64) error { +func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteExternalIDP(v.Db, externalIDPTable, externalUserID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedExternalIDPSequence(eventSequence) + return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64) error { +func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteExternalIDPsByUserID(v.Db, externalIDPTable, userID) if err != nil { return err } - return v.ProcessedExternalIDPSequence(eventSequence) + return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestExternalIDPSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(externalIDPTable) } -func (v *View) ProcessedExternalIDPSequence(eventSequence uint64) error { - return v.saveCurrentSequence(externalIDPTable, eventSequence) +func (v *View) ProcessedExternalIDPSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(externalIDPTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateExternalIDPSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(externalIDPTable) } func (v *View) GetLatestExternalIDPFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/idp_configs.go b/internal/auth/repository/eventsourcing/view/idp_configs.go index 0a218f08d6..df591a7a00 100644 --- a/internal/auth/repository/eventsourcing/view/idp_configs.go +++ b/internal/auth/repository/eventsourcing/view/idp_configs.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -24,28 +25,32 @@ func (v *View) SearchIDPConfigs(request *iam_model.IDPConfigSearchRequest) ([]*i return view.SearchIDPs(v.Db, idpConfigTable, request) } -func (v *View) PutIDPConfig(idp *iam_es_model.IDPConfigView, sequence uint64) error { +func (v *View) PutIDPConfig(idp *iam_es_model.IDPConfigView, sequence uint64, eventTimestamp time.Time) error { err := view.PutIDP(v.Db, idpConfigTable, idp) if err != nil { return err } - return v.ProcessedIDPConfigSequence(sequence) + return v.ProcessedIDPConfigSequence(sequence, eventTimestamp) } -func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64) error { +func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIDP(v.Db, idpConfigTable, idpID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPConfigSequence(eventSequence) + return v.ProcessedIDPConfigSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestIDPConfigSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(idpConfigTable) } -func (v *View) ProcessedIDPConfigSequence(eventSequence uint64) error { - return v.saveCurrentSequence(idpConfigTable, eventSequence) +func (v *View) ProcessedIDPConfigSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(idpConfigTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateIDPConfigSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(idpConfigTable) } func (v *View) GetLatestIDPConfigFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/idp_providers.go b/internal/auth/repository/eventsourcing/view/idp_providers.go index d60ef835d0..cf81e63745 100644 --- a/internal/auth/repository/eventsourcing/view/idp_providers.go +++ b/internal/auth/repository/eventsourcing/view/idp_providers.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -28,44 +29,48 @@ func (v *View) SearchIDPProviders(request *iam_model.IDPProviderSearchRequest) ( return view.SearchIDPProviders(v.Db, idpProviderTable, request) } -func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64) error { +func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64, eventTimestamp time.Time) error { err := view.PutIDPProvider(v.Db, idpProviderTable, provider) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence) + return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) } -func (v *View) PutIDPProviders(sequence uint64, providers ...*model.IDPProviderView) error { +func (v *View) PutIDPProviders(sequence uint64, eventTimestamp time.Time, providers ...*model.IDPProviderView) error { err := view.PutIDPProviders(v.Db, idpProviderTable, providers...) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence) + return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) } -func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64) error { +func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIDPProvider(v.Db, idpProviderTable, aggregateID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPProviderSequence(eventSequence) + return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteIDPProvidersByAggregateID(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteIDPProvidersByAggregateID(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIDPProvidersByAggregateID(v.Db, idpProviderTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPProviderSequence(eventSequence) + return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestIDPProviderSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(idpProviderTable) } -func (v *View) ProcessedIDPProviderSequence(eventSequence uint64) error { - return v.saveCurrentSequence(idpProviderTable, eventSequence) +func (v *View) ProcessedIDPProviderSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(idpProviderTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateIDPProviderSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(idpProviderTable) } func (v *View) GetLatestIDPProviderFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/key.go b/internal/auth/repository/eventsourcing/view/key.go index 9a21afc4d0..c0c0f7d357 100644 --- a/internal/auth/repository/eventsourcing/view/key.go +++ b/internal/auth/repository/eventsourcing/view/key.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/key/repository/view" "github.com/caos/zitadel/internal/key/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -31,36 +32,40 @@ func (v *View) GetActiveKeySet() ([]*key_model.PublicKey, error) { return key_model.PublicKeysFromKeyView(model.KeyViewsToModel(keys), v.keyAlgorithm) } -func (v *View) PutKeys(privateKey, publicKey *model.KeyView, eventSequence uint64) error { +func (v *View) PutKeys(privateKey, publicKey *model.KeyView, eventSequence uint64, eventTimestamp time.Time) error { err := view.PutKeys(v.Db, keyTable, privateKey, publicKey) if err != nil { return err } - return v.ProcessedKeySequence(eventSequence) + return v.ProcessedKeySequence(eventSequence, eventTimestamp) } -func (v *View) DeleteKey(keyID string, private bool, eventSequence uint64) error { +func (v *View) DeleteKey(keyID string, private bool, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteKey(v.Db, keyTable, keyID, private) if err != nil { return nil } - return v.ProcessedKeySequence(eventSequence) + return v.ProcessedKeySequence(eventSequence, eventTimestamp) } -func (v *View) DeleteKeyPair(keyID string, eventSequence uint64) error { +func (v *View) DeleteKeyPair(keyID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteKeyPair(v.Db, keyTable, keyID) if err != nil { return nil } - return v.ProcessedKeySequence(eventSequence) + return v.ProcessedKeySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestKeySequence() (*repository.CurrentSequence, error) { return v.latestSequence(keyTable) } -func (v *View) ProcessedKeySequence(eventSequence uint64) error { - return v.saveCurrentSequence(keyTable, eventSequence) +func (v *View) ProcessedKeySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(keyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateKeySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(keyTable) } func (v *View) GetLatestKeyFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/login_policies.go b/internal/auth/repository/eventsourcing/view/login_policies.go index 3a2133ddee..2da8862129 100644 --- a/internal/auth/repository/eventsourcing/view/login_policies.go +++ b/internal/auth/repository/eventsourcing/view/login_policies.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyV return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID) } -func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64) error { +func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutLoginPolicy(v.Db, loginPolicyTable, policy) if err != nil { return err } - return v.ProcessedLoginPolicySequence(sequence) + return v.ProcessedLoginPolicySequence(sequence, eventTimestamp) } -func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedLoginPolicySequence(eventSequence) + return v.ProcessedLoginPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestLoginPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(loginPolicyTable) } -func (v *View) ProcessedLoginPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(loginPolicyTable, eventSequence) +func (v *View) ProcessedLoginPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(loginPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateLoginPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(loginPolicyTable) } func (v *View) GetLatestLoginPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/machine_keys.go b/internal/auth/repository/eventsourcing/view/machine_keys.go index 03e7c494aa..ac1a442566 100644 --- a/internal/auth/repository/eventsourcing/view/machine_keys.go +++ b/internal/auth/repository/eventsourcing/view/machine_keys.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -27,39 +28,43 @@ func (v *View) SearchMachineKeys(request *usr_model.MachineKeySearchRequest) ([] return view.SearchMachineKeys(v.Db, machineKeyTable, request) } -func (v *View) PutMachineKey(key *model.MachineKeyView, sequence uint64) error { +func (v *View) PutMachineKey(key *model.MachineKeyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutMachineKey(v.Db, machineKeyTable, key) if err != nil { return err } if sequence != 0 { - return v.ProcessedMachineKeySequence(sequence) + return v.ProcessedMachineKeySequence(sequence, eventTimestamp) } return nil } -func (v *View) DeleteMachineKey(keyID string, eventSequence uint64) error { +func (v *View) DeleteMachineKey(keyID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteMachineKey(v.Db, machineKeyTable, keyID) if err != nil { return nil } - return v.ProcessedMachineKeySequence(eventSequence) + return v.ProcessedMachineKeySequence(eventSequence, eventTimestamp) } -func (v *View) DeleteMachineKeysByUserID(userID string, eventSequence uint64) error { +func (v *View) DeleteMachineKeysByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteMachineKey(v.Db, machineKeyTable, userID) if err != nil { return nil } - return v.ProcessedMachineKeySequence(eventSequence) + return v.ProcessedMachineKeySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestMachineKeySequence() (*repository.CurrentSequence, error) { return v.latestSequence(machineKeyTable) } -func (v *View) ProcessedMachineKeySequence(eventSequence uint64) error { - return v.saveCurrentSequence(machineKeyTable, eventSequence) +func (v *View) ProcessedMachineKeySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(machineKeyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateMachineKeySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(machineKeyTable) } func (v *View) GetLatestMachineKeyFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/org.go b/internal/auth/repository/eventsourcing/view/org.go index 6383f62398..9f489f5c30 100644 --- a/internal/auth/repository/eventsourcing/view/org.go +++ b/internal/auth/repository/eventsourcing/view/org.go @@ -5,6 +5,7 @@ import ( org_view "github.com/caos/zitadel/internal/org/repository/view" org_model "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -23,12 +24,12 @@ func (v *View) SearchOrgs(req *model.OrgSearchRequest) ([]*org_model.OrgView, ui return org_view.SearchOrgs(v.Db, orgTable, req) } -func (v *View) PutOrg(org *org_model.OrgView) error { +func (v *View) PutOrg(org *org_model.OrgView, eventTimestamp time.Time) error { err := org_view.PutOrg(v.Db, orgTable, org) if err != nil { return err } - return v.ProcessedOrgSequence(org.Sequence) + return v.ProcessedOrgSequence(org.Sequence, eventTimestamp) } func (v *View) GetLatestOrgFailedEvent(sequence uint64) (*repository.FailedEvent, error) { @@ -39,10 +40,14 @@ func (v *View) ProcessedOrgFailedEvent(failedEvent *repository.FailedEvent) erro return v.saveFailedEvent(failedEvent) } +func (v *View) UpdateOrgSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(orgTable) +} + func (v *View) GetLatestOrgSequence() (*repository.CurrentSequence, error) { return v.latestSequence(orgTable) } -func (v *View) ProcessedOrgSequence(eventSequence uint64) error { - return v.saveCurrentSequence(orgTable, eventSequence) +func (v *View) ProcessedOrgSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(orgTable, eventSequence, eventTimestamp) } diff --git a/internal/auth/repository/eventsourcing/view/org_iam_policy.go b/internal/auth/repository/eventsourcing/view/org_iam_policy.go index 2d43efc80e..a9ee5a295f 100644 --- a/internal/auth/repository/eventsourcing/view/org_iam_policy.go +++ b/internal/auth/repository/eventsourcing/view/org_iam_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) OrgIAMPolicyByAggregateID(aggregateID string) (*model.OrgIAMPolic return view.GetOrgIAMPolicyByAggregateID(v.Db, orgIAMPolicyTable, aggregateID) } -func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64) error { +func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutOrgIAMPolicy(v.Db, orgIAMPolicyTable, policy) if err != nil { return err } - return v.ProcessedOrgIAMPolicySequence(sequence) + return v.ProcessedOrgIAMPolicySequence(sequence, eventTimestamp) } -func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteOrgIAMPolicy(v.Db, orgIAMPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedOrgIAMPolicySequence(eventSequence) + return v.ProcessedOrgIAMPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestOrgIAMPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(orgIAMPolicyTable) } -func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence) +func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateOrgIAMPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(orgIAMPolicyTable) } func (v *View) GetLatestOrgIAMPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/password_complexity_policy.go b/internal/auth/repository/eventsourcing/view/password_complexity_policy.go index 93e28e1eb6..8259c89da0 100644 --- a/internal/auth/repository/eventsourcing/view/password_complexity_policy.go +++ b/internal/auth/repository/eventsourcing/view/password_complexity_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) PasswordComplexityPolicyByAggregateID(aggregateID string) (*model return view.GetPasswordComplexityPolicyByAggregateID(v.Db, passwordComplexityPolicyTable, aggregateID) } -func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64) error { +func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutPasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordComplexityPolicySequence(sequence) + return v.ProcessedPasswordComplexityPolicySequence(sequence, eventTimestamp) } -func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeletePasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordComplexityPolicySequence(eventSequence) + return v.ProcessedPasswordComplexityPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestPasswordComplexityPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(passwordComplexityPolicyTable) } -func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence) +func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdatePasswordComplexityPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(passwordComplexityPolicyTable) } func (v *View) GetLatestPasswordComplexityPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/project_role.go b/internal/auth/repository/eventsourcing/view/project_role.go index fdfe4d9dc1..66c287ffa1 100644 --- a/internal/auth/repository/eventsourcing/view/project_role.go +++ b/internal/auth/repository/eventsourcing/view/project_role.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -31,20 +32,20 @@ func (v *View) SearchProjectRoles(request *proj_model.ProjectRoleSearchRequest) return view.SearchProjectRoles(v.Db, projectRoleTable, request) } -func (v *View) PutProjectRole(project *model.ProjectRoleView) error { +func (v *View) PutProjectRole(project *model.ProjectRoleView, eventTimestamp time.Time) error { err := view.PutProjectRole(v.Db, projectRoleTable, project) if err != nil { return err } - return v.ProcessedProjectRoleSequence(project.Sequence) + return v.ProcessedProjectRoleSequence(project.Sequence, eventTimestamp) } -func (v *View) DeleteProjectRole(projectID, orgID, key string, eventSequence uint64) error { +func (v *View) DeleteProjectRole(projectID, orgID, key string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteProjectRole(v.Db, projectRoleTable, projectID, orgID, key) if err != nil { return nil } - return v.ProcessedProjectRoleSequence(eventSequence) + return v.ProcessedProjectRoleSequence(eventSequence, eventTimestamp) } func (v *View) DeleteProjectRolesByProjectID(projectID string) error { @@ -55,8 +56,12 @@ func (v *View) GetLatestProjectRoleSequence() (*repository.CurrentSequence, erro return v.latestSequence(projectRoleTable) } -func (v *View) ProcessedProjectRoleSequence(eventSequence uint64) error { - return v.saveCurrentSequence(projectRoleTable, eventSequence) +func (v *View) ProcessedProjectRoleSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(projectRoleTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateProjectRoleSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(projectRoleTable) } func (v *View) GetLatestProjectRoleFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/sequence.go b/internal/auth/repository/eventsourcing/view/sequence.go index d65b6e4da6..4ac2ab80cc 100644 --- a/internal/auth/repository/eventsourcing/view/sequence.go +++ b/internal/auth/repository/eventsourcing/view/sequence.go @@ -2,16 +2,29 @@ package view import ( "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( sequencesTable = "auth.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence) +func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimestamp time.Time) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimestamp) } func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { return repository.LatestSequence(v.Db, sequencesTable, viewName) } + +func (v *View) updateSpoolerRunSequence(viewName string) error { + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + if err != nil { + return err + } + if currentSequence.ViewName == "" { + currentSequence.ViewName = viewName + } + currentSequence.LastSuccessfulSpoolerRun = time.Now() + return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) +} diff --git a/internal/auth/repository/eventsourcing/view/token.go b/internal/auth/repository/eventsourcing/view/token.go index 94ecabd9b3..4cb7c41844 100644 --- a/internal/auth/repository/eventsourcing/view/token.go +++ b/internal/auth/repository/eventsourcing/view/token.go @@ -4,6 +4,7 @@ import ( usr_view "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -18,60 +19,64 @@ func (v *View) TokensByUserID(userID string) ([]*model.TokenView, error) { return usr_view.TokensByUserID(v.Db, tokenTable, userID) } -func (v *View) PutToken(token *model.TokenView) error { +func (v *View) PutToken(token *model.TokenView, eventTimestamp time.Time) error { err := usr_view.PutToken(v.Db, tokenTable, token) if err != nil { return err } - return v.ProcessedTokenSequence(token.Sequence) + return v.ProcessedTokenSequence(token.Sequence, eventTimestamp) } -func (v *View) PutTokens(token []*model.TokenView, sequence uint64) error { +func (v *View) PutTokens(token []*model.TokenView, sequence uint64, eventTimestamp time.Time) error { err := usr_view.PutTokens(v.Db, tokenTable, token...) if err != nil { return err } - return v.ProcessedTokenSequence(sequence) + return v.ProcessedTokenSequence(sequence, eventTimestamp) } -func (v *View) DeleteToken(tokenID string, eventSequence uint64) error { +func (v *View) DeleteToken(tokenID string, eventSequence uint64, eventTimestamp time.Time) error { err := usr_view.DeleteToken(v.Db, tokenTable, tokenID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence) + return v.ProcessedTokenSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteSessionTokens(agentID, userID string, eventSequence uint64) error { +func (v *View) DeleteSessionTokens(agentID, userID string, eventSequence uint64, eventTimestamp time.Time) error { err := usr_view.DeleteSessionTokens(v.Db, tokenTable, agentID, userID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence) + return v.ProcessedTokenSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteUserTokens(userID string, eventSequence uint64) error { +func (v *View) DeleteUserTokens(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := usr_view.DeleteUserTokens(v.Db, tokenTable, userID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence) + return v.ProcessedTokenSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteApplicationTokens(eventSequence uint64, ids ...string) error { +func (v *View) DeleteApplicationTokens(eventSequence uint64, eventTimestamp time.Time, ids ...string) error { err := usr_view.DeleteApplicationTokens(v.Db, tokenTable, ids) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence) + return v.ProcessedTokenSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestTokenSequence() (*repository.CurrentSequence, error) { return v.latestSequence(tokenTable) } -func (v *View) ProcessedTokenSequence(eventSequence uint64) error { - return v.saveCurrentSequence(tokenTable, eventSequence) +func (v *View) ProcessedTokenSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(tokenTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateTokenSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(tokenTable) } func (v *View) GetLatestTokenFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/user.go b/internal/auth/repository/eventsourcing/view/user.go index 5472eb628d..a0a4c479fb 100644 --- a/internal/auth/repository/eventsourcing/view/user.go +++ b/internal/auth/repository/eventsourcing/view/user.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -51,36 +52,40 @@ func (v *View) UserMfas(userID string) ([]*usr_model.MultiFactor, error) { return view.UserMfas(v.Db, userTable, userID) } -func (v *View) PutUser(user *model.UserView, sequence uint64) error { +func (v *View) PutUser(user *model.UserView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUser(v.Db, userTable, user) if err != nil { return err } - return v.ProcessedUserSequence(sequence) + return v.ProcessedUserSequence(sequence, eventTimestamp) } -func (v *View) PutUsers(users []*model.UserView, sequence uint64) error { +func (v *View) PutUsers(users []*model.UserView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUsers(v.Db, userTable, users...) if err != nil { return err } - return v.ProcessedUserSequence(sequence) + return v.ProcessedUserSequence(sequence, eventTimestamp) } -func (v *View) DeleteUser(userID string, eventSequence uint64) error { +func (v *View) DeleteUser(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUser(v.Db, userTable, userID) if err != nil { return nil } - return v.ProcessedUserSequence(eventSequence) + return v.ProcessedUserSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestUserSequence() (*repository.CurrentSequence, error) { return v.latestSequence(userTable) } -func (v *View) ProcessedUserSequence(eventSequence uint64) error { - return v.saveCurrentSequence(userTable, eventSequence) +func (v *View) ProcessedUserSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(userTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateUserSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(userTable) } func (v *View) GetLatestUserFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/user_grant.go b/internal/auth/repository/eventsourcing/view/user_grant.go index cc53b97504..230e9f5c8a 100644 --- a/internal/auth/repository/eventsourcing/view/user_grant.go +++ b/internal/auth/repository/eventsourcing/view/user_grant.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/usergrant/repository/view" "github.com/caos/zitadel/internal/usergrant/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -35,36 +36,40 @@ func (v *View) SearchUserGrants(request *grant_model.UserGrantSearchRequest) ([] return view.SearchUserGrants(v.Db, userGrantTable, request) } -func (v *View) PutUserGrant(grant *model.UserGrantView, sequence uint64) error { +func (v *View) PutUserGrant(grant *model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserGrant(v.Db, userGrantTable, grant) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence) + return v.ProcessedUserGrantSequence(sequence, eventTimestamp) } -func (v *View) PutUserGrants(grants []*model.UserGrantView, sequence uint64) error { +func (v *View) PutUserGrants(grants []*model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserGrants(v.Db, userGrantTable, grants...) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence) + return v.ProcessedUserGrantSequence(sequence, eventTimestamp) } -func (v *View) DeleteUserGrant(grantID string, eventSequence uint64) error { +func (v *View) DeleteUserGrant(grantID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserGrant(v.Db, userGrantTable, grantID) if err != nil { return nil } - return v.ProcessedUserGrantSequence(eventSequence) + return v.ProcessedUserGrantSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestUserGrantSequence() (*repository.CurrentSequence, error) { return v.latestSequence(userGrantTable) } -func (v *View) ProcessedUserGrantSequence(eventSequence uint64) error { - return v.saveCurrentSequence(userGrantTable, eventSequence) +func (v *View) ProcessedUserGrantSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(userGrantTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateUserGrantSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(userGrantTable) } func (v *View) GetLatestUserGrantFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/user_membership.go b/internal/auth/repository/eventsourcing/view/user_membership.go index cbd241e350..84607584ab 100644 --- a/internal/auth/repository/eventsourcing/view/user_membership.go +++ b/internal/auth/repository/eventsourcing/view/user_membership.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -27,60 +28,64 @@ func (v *View) SearchUserMemberships(request *usr_model.UserMembershipSearchRequ return view.SearchUserMemberships(v.Db, userMembershipTable, request) } -func (v *View) PutUserMembership(membership *model.UserMembershipView, sequence uint64) error { +func (v *View) PutUserMembership(membership *model.UserMembershipView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserMembership(v.Db, userMembershipTable, membership) if err != nil { return err } - return v.ProcessedUserMembershipSequence(sequence) + return v.ProcessedUserMembershipSequence(sequence, eventTimestamp) } -func (v *View) BulkPutUserMemberships(memberships []*model.UserMembershipView, sequence uint64) error { +func (v *View) BulkPutUserMemberships(memberships []*model.UserMembershipView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserMemberships(v.Db, userMembershipTable, memberships...) if err != nil { return err } - return v.ProcessedUserMembershipSequence(sequence) + return v.ProcessedUserMembershipSequence(sequence, eventTimestamp) } -func (v *View) DeleteUserMembership(userID, aggregateID, objectID string, memberType usr_model.MemberType, eventSequence uint64) error { +func (v *View) DeleteUserMembership(userID, aggregateID, objectID string, memberType usr_model.MemberType, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserMembership(v.Db, userMembershipTable, userID, aggregateID, objectID, memberType) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence) + return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteUserMembershipsByUserID(userID string, eventSequence uint64) error { +func (v *View) DeleteUserMembershipsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserMembershipsByUserID(v.Db, userMembershipTable, userID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence) + return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteUserMembershipsByAggregateID(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteUserMembershipsByAggregateID(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserMembershipsByAggregateID(v.Db, userMembershipTable, aggregateID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence) + return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteUserMembershipsByAggregateIDAndObjectID(aggregateID, objectID string, eventSequence uint64) error { +func (v *View) DeleteUserMembershipsByAggregateIDAndObjectID(aggregateID, objectID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserMembershipsByAggregateIDAndObjectID(v.Db, userMembershipTable, aggregateID, objectID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence) + return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestUserMembershipSequence() (*repository.CurrentSequence, error) { return v.latestSequence(userMembershipTable) } -func (v *View) ProcessedUserMembershipSequence(eventSequence uint64) error { - return v.saveCurrentSequence(userMembershipTable, eventSequence) +func (v *View) ProcessedUserMembershipSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(userMembershipTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateUserMembershipSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(userMembershipTable) } func (v *View) GetLatestUserMembershipFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/auth/repository/eventsourcing/view/user_session.go b/internal/auth/repository/eventsourcing/view/user_session.go index fe9d6b0ec2..805cc04aef 100644 --- a/internal/auth/repository/eventsourcing/view/user_session.go +++ b/internal/auth/repository/eventsourcing/view/user_session.go @@ -4,6 +4,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -22,36 +23,44 @@ func (v *View) UserSessionsByAgentID(agentID string) ([]*model.UserSessionView, return view.UserSessionsByAgentID(v.Db, userSessionTable, agentID) } -func (v *View) PutUserSession(userSession *model.UserSessionView) error { +func (v *View) ActiveUserSessions() ([]*model.UserSessionView, error) { + return view.ActiveUserSessions(v.Db, userSessionTable) +} + +func (v *View) PutUserSession(userSession *model.UserSessionView, eventTimestamp time.Time) error { err := view.PutUserSession(v.Db, userSessionTable, userSession) if err != nil { return err } - return v.ProcessedUserSessionSequence(userSession.Sequence) + return v.ProcessedUserSessionSequence(userSession.Sequence, eventTimestamp) } -func (v *View) PutUserSessions(userSession []*model.UserSessionView, sequence uint64) error { +func (v *View) PutUserSessions(userSession []*model.UserSessionView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserSessions(v.Db, userSessionTable, userSession...) if err != nil { return err } - return v.ProcessedUserSessionSequence(sequence) + return v.ProcessedUserSessionSequence(sequence, eventTimestamp) } -func (v *View) DeleteUserSessions(userID string, eventSequence uint64) error { +func (v *View) DeleteUserSessions(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserSessions(v.Db, userSessionTable, userID) if err != nil { return nil } - return v.ProcessedUserSessionSequence(eventSequence) + return v.ProcessedUserSessionSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestUserSessionSequence() (*repository.CurrentSequence, error) { return v.latestSequence(userSessionTable) } -func (v *View) ProcessedUserSessionSequence(eventSequence uint64) error { - return v.saveCurrentSequence(userSessionTable, eventSequence) +func (v *View) ProcessedUserSessionSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(userSessionTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateUserSessionSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(userSessionTable) } func (v *View) GetLatestUserSessionFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/auth/repository/user_session.go b/internal/auth/repository/user_session.go index 98e8751d07..f6eca64de2 100644 --- a/internal/auth/repository/user_session.go +++ b/internal/auth/repository/user_session.go @@ -7,4 +7,5 @@ import ( type UserSessionRepository interface { GetMyUserSessions(ctx context.Context) ([]*model.UserSessionView, error) + ActiveUserSessionCount() int64 } diff --git a/internal/authz/repository/eventsourcing/eventstore/token_verifier.go b/internal/authz/repository/eventsourcing/eventstore/token_verifier.go index 04b6966a97..a6a0160edf 100644 --- a/internal/authz/repository/eventsourcing/eventstore/token_verifier.go +++ b/internal/authz/repository/eventsourcing/eventstore/token_verifier.go @@ -15,7 +15,7 @@ import ( caos_errs "github.com/caos/zitadel/internal/errors" iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing" proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) type TokenVerifierRepo struct { diff --git a/internal/authz/repository/eventsourcing/handler/application.go b/internal/authz/repository/eventsourcing/handler/application.go index 401f761ad0..4b5773607e 100644 --- a/internal/authz/repository/eventsourcing/handler/application.go +++ b/internal/authz/repository/eventsourcing/handler/application.go @@ -54,17 +54,21 @@ func (a *Application) Reduce(event *models.Event) (err error) { if err != nil { return err } - return a.view.DeleteApplication(app.ID, event.Sequence) + return a.view.DeleteApplication(app.ID, event.Sequence, event.CreationDate) default: - return a.view.ProcessedApplicationSequence(event.Sequence) + return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return a.view.PutApplication(app) + return a.view.PutApplication(app, event.CreationDate) } func (a *Application) OnError(event *models.Event, spoolerError error) error { logging.LogWithFields("SPOOL-sjZw", "id", event.AggregateID).WithError(spoolerError).Warn("something went wrong in project app handler") return spooler.HandleError(event, spoolerError, a.view.GetLatestApplicationFailedEvent, a.view.ProcessedApplicationFailedEvent, a.view.ProcessedApplicationSequence, a.errorCountUntilSkip) } + +func (a *Application) OnSuccess() error { + return spooler.HandleSuccess(a.view.UpdateApplicationSpoolerRunTimestamp) +} diff --git a/internal/authz/repository/eventsourcing/handler/org.go b/internal/authz/repository/eventsourcing/handler/org.go index 79bc52b7b6..e487831f02 100644 --- a/internal/authz/repository/eventsourcing/handler/org.go +++ b/internal/authz/repository/eventsourcing/handler/org.go @@ -53,13 +53,17 @@ func (o *Org) Reduce(event *es_models.Event) error { return err } default: - return o.view.ProcessedOrgSequence(event.Sequence) + return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate) } - return o.view.PutOrg(org) + return o.view.PutOrg(org, event.CreationDate) } func (o *Org) OnError(event *es_models.Event, spoolerErr error) error { logging.LogWithFields("SPOOL-8siWS", "id", event.AggregateID).WithError(spoolerErr).Warn("something went wrong in org handler") return spooler.HandleError(event, spoolerErr, o.view.GetLatestOrgFailedEvent, o.view.ProcessedOrgFailedEvent, o.view.ProcessedOrgSequence, o.errorCountUntilSkip) } + +func (o *Org) OnSuccess() error { + return spooler.HandleSuccess(o.view.UpdateOrgSpoolerRunTimestamp) +} diff --git a/internal/authz/repository/eventsourcing/handler/user_grant.go b/internal/authz/repository/eventsourcing/handler/user_grant.go index 897186b8e8..58cd01d31c 100644 --- a/internal/authz/repository/eventsourcing/handler/user_grant.go +++ b/internal/authz/repository/eventsourcing/handler/user_grant.go @@ -75,7 +75,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { member.SetData(event) return u.processMember(event, "PROJECT_GRANT", member.GrantID, member.UserID, member.Roles) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } } @@ -86,7 +86,7 @@ func (u *UserGrant) processOrg(event *models.Event) (err error) { member.SetData(event) return u.processMember(event, "ORG", "", member.UserID, member.Roles) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } } @@ -124,16 +124,16 @@ func (u *UserGrant) processIAMMember(event *models.Event, rolePrefix string, suf } grant.Sequence = event.Sequence grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, grant.Sequence) + return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate) case iam_es_model.IAMMemberRemoved: member.SetData(event) grant, err := u.view.UserGrantByIDs(u.iamID, u.iamProjectID, member.UserID) if err != nil { return err } - return u.view.DeleteUserGrant(grant.ID, event.Sequence) + return u.view.DeleteUserGrant(grant.ID, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } } @@ -169,7 +169,7 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st } grant.Sequence = event.Sequence grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, event.Sequence) + return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate) case org_es_model.OrgMemberRemoved, proj_es_model.ProjectMemberRemoved, proj_es_model.ProjectGrantMemberRemoved: @@ -179,18 +179,18 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st return err } if errors.IsNotFound(err) { - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } if roleSuffix != "" { roleKeys = suffixRoles(roleSuffix, roleKeys) } if grant.RoleKeys == nil { - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } grant.RoleKeys = mergeExistingRoles(rolePrefix, roleSuffix, grant.RoleKeys, nil) - return u.view.PutUserGrant(grant, event.Sequence) + return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } } @@ -235,3 +235,7 @@ func (u *UserGrant) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-VcVoJ", "id", event.AggregateID).WithError(err).Warn("something went wrong in user grant handler") return spooler.HandleError(event, err, u.view.GetLatestUserGrantFailedEvent, u.view.ProcessedUserGrantFailedEvent, u.view.ProcessedUserGrantSequence, u.errorCountUntilSkip) } + +func (u *UserGrant) OnSuccess() error { + return spooler.HandleSuccess(u.view.UpdateUserGrantSpoolerRunTimestamp) +} diff --git a/internal/authz/repository/eventsourcing/view/application.go b/internal/authz/repository/eventsourcing/view/application.go index bb82b4d62f..a8e772b58d 100644 --- a/internal/authz/repository/eventsourcing/view/application.go +++ b/internal/authz/repository/eventsourcing/view/application.go @@ -2,11 +2,12 @@ package view import ( "context" + "time" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" "github.com/caos/zitadel/internal/view/repository" ) @@ -33,28 +34,32 @@ func (v *View) SearchApplications(request *proj_model.ApplicationSearchRequest) return view.SearchApplications(v.Db, applicationTable, request) } -func (v *View) PutApplication(project *model.ApplicationView) error { +func (v *View) PutApplication(project *model.ApplicationView, eventTimestamp time.Time) error { err := view.PutApplication(v.Db, applicationTable, project) if err != nil { return err } - return v.ProcessedApplicationSequence(project.Sequence) + return v.ProcessedApplicationSequence(project.Sequence, eventTimestamp) } -func (v *View) DeleteApplication(appID string, eventSequence uint64) error { +func (v *View) DeleteApplication(appID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteApplication(v.Db, applicationTable, appID) if err != nil { return nil } - return v.ProcessedApplicationSequence(eventSequence) + return v.ProcessedApplicationSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestApplicationSequence() (*repository.CurrentSequence, error) { return v.latestSequence(applicationTable) } -func (v *View) ProcessedApplicationSequence(eventSequence uint64) error { - return v.saveCurrentSequence(applicationTable, eventSequence) +func (v *View) ProcessedApplicationSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(applicationTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateApplicationSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(applicationTable) } func (v *View) GetLatestApplicationFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/authz/repository/eventsourcing/view/org.go b/internal/authz/repository/eventsourcing/view/org.go index fe9d6d51c2..f886123b2e 100644 --- a/internal/authz/repository/eventsourcing/view/org.go +++ b/internal/authz/repository/eventsourcing/view/org.go @@ -5,6 +5,7 @@ import ( org_view "github.com/caos/zitadel/internal/org/repository/view" org_model "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -19,12 +20,12 @@ func (v *View) SearchOrgs(req *model.OrgSearchRequest) ([]*org_model.OrgView, ui return org_view.SearchOrgs(v.Db, orgTable, req) } -func (v *View) PutOrg(org *org_model.OrgView) error { +func (v *View) PutOrg(org *org_model.OrgView, eventTimestamp time.Time) error { err := org_view.PutOrg(v.Db, orgTable, org) if err != nil { return err } - return v.ProcessedOrgSequence(org.Sequence) + return v.ProcessedOrgSequence(org.Sequence, eventTimestamp) } func (v *View) GetLatestOrgFailedEvent(sequence uint64) (*repository.FailedEvent, error) { @@ -39,6 +40,10 @@ func (v *View) GetLatestOrgSequence() (*repository.CurrentSequence, error) { return v.latestSequence(orgTable) } -func (v *View) ProcessedOrgSequence(eventSequence uint64) error { - return v.saveCurrentSequence(orgTable, eventSequence) +func (v *View) ProcessedOrgSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(orgTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateOrgSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(orgTable) } diff --git a/internal/authz/repository/eventsourcing/view/sequence.go b/internal/authz/repository/eventsourcing/view/sequence.go index 815bcfebf8..ad628fbf7b 100644 --- a/internal/authz/repository/eventsourcing/view/sequence.go +++ b/internal/authz/repository/eventsourcing/view/sequence.go @@ -2,16 +2,29 @@ package view import ( "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( sequencesTable = "authz.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence) +func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimestamp time.Time) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimestamp) } func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { return repository.LatestSequence(v.Db, sequencesTable, viewName) } + +func (v *View) updateSpoolerRunSequence(viewName string) error { + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + if err != nil { + return err + } + if currentSequence.ViewName == "" { + currentSequence.ViewName = viewName + } + currentSequence.LastSuccessfulSpoolerRun = time.Now() + return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) +} diff --git a/internal/authz/repository/eventsourcing/view/token.go b/internal/authz/repository/eventsourcing/view/token.go index 7c5a7163f6..bab80f238a 100644 --- a/internal/authz/repository/eventsourcing/view/token.go +++ b/internal/authz/repository/eventsourcing/view/token.go @@ -4,6 +4,7 @@ import ( usr_view "github.com/caos/zitadel/internal/user/repository/view" usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -14,36 +15,40 @@ func (v *View) TokenByID(tokenID string) (*usr_view_model.TokenView, error) { return usr_view.TokenByID(v.Db, tokenTable, tokenID) } -func (v *View) PutToken(token *usr_view_model.TokenView) error { +func (v *View) PutToken(token *usr_view_model.TokenView, eventTimestamp time.Time) error { err := usr_view.PutToken(v.Db, tokenTable, token) if err != nil { return err } - return v.ProcessedTokenSequence(token.Sequence) + return v.ProcessedTokenSequence(token.Sequence, eventTimestamp) } -func (v *View) DeleteToken(tokenID string, eventSequence uint64) error { +func (v *View) DeleteToken(tokenID string, eventSequence uint64, eventTimestamp time.Time) error { err := usr_view.DeleteToken(v.Db, tokenTable, tokenID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence) + return v.ProcessedTokenSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteSessionTokens(agentID, userID string, eventSequence uint64) error { +func (v *View) DeleteSessionTokens(agentID, userID string, eventSequence uint64, eventTimestamp time.Time) error { err := usr_view.DeleteSessionTokens(v.Db, tokenTable, agentID, userID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence) + return v.ProcessedTokenSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestTokenSequence() (*repository.CurrentSequence, error) { return v.latestSequence(tokenTable) } -func (v *View) ProcessedTokenSequence(eventSequence uint64) error { - return v.saveCurrentSequence(tokenTable, eventSequence) +func (v *View) ProcessedTokenSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(tokenTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateTokenSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(tokenTable) } func (v *View) GetLatestTokenFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/authz/repository/eventsourcing/view/user_grant.go b/internal/authz/repository/eventsourcing/view/user_grant.go index cc44af9a75..68154dc3c9 100644 --- a/internal/authz/repository/eventsourcing/view/user_grant.go +++ b/internal/authz/repository/eventsourcing/view/user_grant.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/usergrant/repository/view" "github.com/caos/zitadel/internal/usergrant/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -31,28 +32,32 @@ func (v *View) SearchUserGrants(request *grant_model.UserGrantSearchRequest) ([] return view.SearchUserGrants(v.Db, userGrantTable, request) } -func (v *View) PutUserGrant(grant *model.UserGrantView, sequence uint64) error { +func (v *View) PutUserGrant(grant *model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserGrant(v.Db, userGrantTable, grant) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence) + return v.ProcessedUserGrantSequence(sequence, eventTimestamp) } -func (v *View) DeleteUserGrant(grantID string, eventSequence uint64) error { +func (v *View) DeleteUserGrant(grantID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserGrant(v.Db, userGrantTable, grantID) if err != nil { return nil } - return v.ProcessedUserGrantSequence(eventSequence) + return v.ProcessedUserGrantSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestUserGrantSequence() (*repository.CurrentSequence, error) { return v.latestSequence(userGrantTable) } -func (v *View) ProcessedUserGrantSequence(eventSequence uint64) error { - return v.saveCurrentSequence(userGrantTable, eventSequence) +func (v *View) ProcessedUserGrantSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(userGrantTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateUserGrantSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(userGrantTable) } func (v *View) GetLatestUserGrantFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/eventstore/internal/repository/sql/filter.go b/internal/eventstore/internal/repository/sql/filter.go index 0b393f885f..e9a98939da 100644 --- a/internal/eventstore/internal/repository/sql/filter.go +++ b/internal/eventstore/internal/repository/sql/filter.go @@ -8,7 +8,7 @@ import ( "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) type Querier interface { diff --git a/internal/eventstore/internal/repository/sql/push.go b/internal/eventstore/internal/repository/sql/push.go index b6af36cce0..3a3802ebf2 100644 --- a/internal/eventstore/internal/repository/sql/push.go +++ b/internal/eventstore/internal/repository/sql/push.go @@ -8,7 +8,7 @@ import ( "github.com/caos/logging" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/models" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" "github.com/cockroachdb/cockroach-go/v2/crdb" ) diff --git a/internal/eventstore/query/handler.go b/internal/eventstore/query/handler.go index 8effb168c0..36bba2547e 100755 --- a/internal/eventstore/query/handler.go +++ b/internal/eventstore/query/handler.go @@ -11,6 +11,7 @@ type Handler interface { EventQuery() (*models.SearchQuery, error) Reduce(*models.Event) error OnError(event *models.Event, err error) error + OnSuccess() error MinimumCycleDuration() time.Duration QueryLimit() uint64 } diff --git a/internal/eventstore/spooler/config.go b/internal/eventstore/spooler/config.go index fbad7d0496..fa796f06c3 100644 --- a/internal/eventstore/spooler/config.go +++ b/internal/eventstore/spooler/config.go @@ -28,7 +28,7 @@ func (c *Config) New() *Spooler { lockID: lockID, eventstore: c.Eventstore, locker: c.Locker, - queue: make(chan *spooledHandler), + queue: make(chan *spooledHandler, len(c.ViewHandlers)), workers: c.ConcurrentWorkers, } } diff --git a/internal/eventstore/spooler/spooler.go b/internal/eventstore/spooler/spooler.go index d95f45ad4a..fb480f7916 100644 --- a/internal/eventstore/spooler/spooler.go +++ b/internal/eventstore/spooler/spooler.go @@ -9,7 +9,7 @@ import ( "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/eventstore/query" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" "github.com/caos/zitadel/internal/view/repository" "time" @@ -52,8 +52,7 @@ func (s *Spooler) Start() { } go func() { for _, handler := range s.handlers { - handler := &spooledHandler{Handler: handler, locker: s.locker, queuedAt: time.Now(), eventstore: s.eventstore} - s.queue <- handler + s.queue <- &spooledHandler{Handler: handler, locker: s.locker, queuedAt: time.Now(), eventstore: s.eventstore} } }() } @@ -79,6 +78,7 @@ func (s *spooledHandler) load(workerID string) { errs <- s.process(ctx, events, workerID) logging.Log("SPOOL-0pV8o").WithField("view", s.ViewModel()).WithField("worker", workerID).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("process done") } + } <-ctx.Done() } @@ -103,7 +103,9 @@ func (s *spooledHandler) process(ctx context.Context, events []*models.Event, wo } } } - return nil + err := s.OnSuccess() + logging.LogWithFields("SPOOL-49ods", "view", s.ViewModel(), "worker", workerID, "traceID", tracing.TraceIDFromCtx(ctx)).OnError(err).Warn("could not process on success func") + return err } func (s *spooledHandler) query(ctx context.Context) ([]*models.Event, error) { @@ -165,7 +167,7 @@ func (s *spooledHandler) lock(ctx context.Context, errs chan<- error, workerID s func HandleError(event *models.Event, failedErr error, latestFailedEvent func(sequence uint64) (*repository.FailedEvent, error), processFailedEvent func(*repository.FailedEvent) error, - processSequence func(uint64) error, errorCountUntilSkip uint64) error { + processSequence func(uint64, time.Time) error, errorCountUntilSkip uint64) error { failedEvent, err := latestFailedEvent(event.Sequence) if err != nil { return err @@ -177,7 +179,11 @@ func HandleError(event *models.Event, failedErr error, return err } if errorCountUntilSkip <= failedEvent.FailureCount { - return processSequence(event.Sequence) + return processSequence(event.Sequence, event.CreationDate) } return nil } + +func HandleSuccess(updateSpoolerRunTimestamp func() error) error { + return updateSpoolerRunTimestamp() +} diff --git a/internal/eventstore/spooler/spooler_test.go b/internal/eventstore/spooler/spooler_test.go index 7a852ed871..721ad74e26 100644 --- a/internal/eventstore/spooler/spooler_test.go +++ b/internal/eventstore/spooler/spooler_test.go @@ -40,6 +40,9 @@ func (h *testHandler) Reduce(*models.Event) error { func (h *testHandler) OnError(event *models.Event, err error) error { return err } +func (h *testHandler) OnSuccess() error { + return nil +} func (h *testHandler) MinimumCycleDuration() time.Duration { return h.cycleDuration } @@ -429,7 +432,7 @@ func TestHandleError(t *testing.T) { func(*repository.FailedEvent) error { return nil }, - func(uint64) error { + func(uint64, time.Time) error { processedSequence = true return nil }, diff --git a/internal/iam/repository/eventsourcing/eventstore.go b/internal/iam/repository/eventsourcing/eventstore.go index c2fad65924..e1ed4d2d26 100644 --- a/internal/iam/repository/eventsourcing/eventstore.go +++ b/internal/iam/repository/eventsourcing/eventstore.go @@ -14,7 +14,7 @@ import ( iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" "github.com/caos/zitadel/internal/id" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" ) type IAMEventstore struct { diff --git a/internal/management/repository/eventsourcing/eventstore/org.go b/internal/management/repository/eventsourcing/eventstore/org.go index ffb6335a28..6bc11af854 100644 --- a/internal/management/repository/eventsourcing/eventstore/org.go +++ b/internal/management/repository/eventsourcing/eventstore/org.go @@ -22,7 +22,7 @@ import ( org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing" org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" "github.com/caos/zitadel/internal/org/repository/view/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" usr_model "github.com/caos/zitadel/internal/user/model" usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing" ) @@ -122,7 +122,7 @@ func (repo *OrgRepository) SearchMyOrgDomains(ctx context.Context, request *org_ } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -219,7 +219,7 @@ func (repo *OrgRepository) SearchMyOrgMembers(ctx context.Context, request *org_ } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -306,7 +306,7 @@ func (repo *OrgRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -414,9 +414,9 @@ func (repo *OrgRepository) SearchIDPProviders(ctx context.Context, request *iam_ request.AppendAggregateIDQuery(authz.GetCtxData(ctx).OrgID) } request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestIdpProviderSequence() + sequence, sequenceErr := repo.View.GetLatestIDPProviderSequence() logging.Log("EVENT-Tuiks").OnError(sequenceErr).Warn("could not read latest iam sequence") - providers, count, err := repo.View.SearchIdpProviders(request) + providers, count, err := repo.View.SearchIDPProviders(request) if err != nil { return nil, err } @@ -428,7 +428,7 @@ func (repo *OrgRepository) SearchIDPProviders(ctx context.Context, request *iam_ } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } diff --git a/internal/management/repository/eventsourcing/eventstore/project.go b/internal/management/repository/eventsourcing/eventstore/project.go index 432bee10dc..5a9343ff11 100644 --- a/internal/management/repository/eventsourcing/eventstore/project.go +++ b/internal/management/repository/eventsourcing/eventstore/project.go @@ -141,7 +141,7 @@ func (repo *ProjectRepo) SearchProjects(ctx context.Context, request *proj_model } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -162,7 +162,7 @@ func (repo *ProjectRepo) SearchProjects(ctx context.Context, request *proj_model } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -212,7 +212,7 @@ func (repo *ProjectRepo) SearchProjectMembers(ctx context.Context, request *proj } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -285,7 +285,7 @@ func (repo *ProjectRepo) SearchProjectRoles(ctx context.Context, projectID strin } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -380,7 +380,7 @@ func (repo *ProjectRepo) SearchApplications(ctx context.Context, request *proj_m } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -437,7 +437,7 @@ func (repo *ProjectRepo) SearchProjectGrants(ctx context.Context, request *proj_ } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -467,7 +467,7 @@ func (repo *ProjectRepo) SearchGrantedProjects(ctx context.Context, request *pro } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -488,7 +488,7 @@ func (repo *ProjectRepo) SearchGrantedProjects(ctx context.Context, request *pro } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -626,7 +626,7 @@ func (repo *ProjectRepo) SearchProjectGrantMembers(ctx context.Context, request } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } diff --git a/internal/management/repository/eventsourcing/eventstore/user.go b/internal/management/repository/eventsourcing/eventstore/user.go index 3ab8118411..576dedd367 100644 --- a/internal/management/repository/eventsourcing/eventstore/user.go +++ b/internal/management/repository/eventsourcing/eventstore/user.go @@ -172,7 +172,7 @@ func (repo *UserRepo) SearchUsers(ctx context.Context, request *usr_model.UserSe } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -274,7 +274,7 @@ func (repo *UserRepo) SearchExternalIDPs(ctx context.Context, request *usr_model } if seqErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -311,7 +311,7 @@ func (repo *UserRepo) SearchMachineKeys(ctx context.Context, request *usr_model. } if seqErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -419,7 +419,7 @@ func (repo *UserRepo) SearchUserMemberships(ctx context.Context, request *usr_mo } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -459,7 +459,7 @@ func handleSearchUserMembershipsPermissions(ctx context.Context, request *usr_mo } if sequence != nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result } diff --git a/internal/management/repository/eventsourcing/eventstore/user_grant.go b/internal/management/repository/eventsourcing/eventstore/user_grant.go index ddcfedb81d..09568b64fc 100644 --- a/internal/management/repository/eventsourcing/eventstore/user_grant.go +++ b/internal/management/repository/eventsourcing/eventstore/user_grant.go @@ -137,7 +137,7 @@ func (repo *UserGrantRepo) SearchUserGrants(ctx context.Context, request *grant_ } if sequenceErr == nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result, nil } @@ -183,7 +183,7 @@ func checkContainsPermID(ids []string, query *grant_model.UserGrantSearchQuery, } if sequence != nil { result.Sequence = sequence.CurrentSequence - result.Timestamp = sequence.CurrentTimestamp + result.Timestamp = sequence.LastSuccessfulSpoolerRun } return result } diff --git a/internal/management/repository/eventsourcing/handler/application.go b/internal/management/repository/eventsourcing/handler/application.go index 4395737197..8d1490c433 100644 --- a/internal/management/repository/eventsourcing/handler/application.go +++ b/internal/management/repository/eventsourcing/handler/application.go @@ -65,33 +65,37 @@ func (a *Application) Reduce(event *models.Event) (err error) { if err != nil { return err } - return a.view.DeleteApplication(app.ID, event.Sequence) + return a.view.DeleteApplication(app.ID, event.Sequence, event.CreationDate) case es_model.ProjectChanged: apps, err := a.view.ApplicationsByProjectID(event.AggregateID) if err != nil { return err } if len(apps) == 0 { - return a.view.ProcessedApplicationSequence(event.Sequence) + return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) } for _, app := range apps { if err := app.AppendEvent(event); err != nil { return err } } - return a.view.PutApplications(apps, event.Sequence) + return a.view.PutApplications(apps, event.Sequence, event.CreationDate) case es_model.ProjectRemoved: return a.view.DeleteApplicationsByProjectID(event.AggregateID) default: - return a.view.ProcessedApplicationSequence(event.Sequence) + return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return a.view.PutApplication(app) + return a.view.PutApplication(app, event.CreationDate) } func (a *Application) OnError(event *models.Event, spoolerError error) error { logging.LogWithFields("SPOOL-ls9ew", "id", event.AggregateID).WithError(spoolerError).Warn("something went wrong in project app handler") return spooler.HandleError(event, spoolerError, a.view.GetLatestApplicationFailedEvent, a.view.ProcessedApplicationFailedEvent, a.view.ProcessedApplicationSequence, a.errorCountUntilSkip) } + +func (a *Application) OnSuccess() error { + return spooler.HandleSuccess(a.view.UpdateApplicationSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/idp_config.go b/internal/management/repository/eventsourcing/handler/idp_config.go index 7ce0e6c487..07301c71b8 100644 --- a/internal/management/repository/eventsourcing/handler/idp_config.go +++ b/internal/management/repository/eventsourcing/handler/idp_config.go @@ -66,17 +66,21 @@ func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, eve if err != nil { return err } - return m.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence) + return m.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedIDPConfigSequence(event.Sequence) + return m.view.ProcessedIDPConfigSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutIDPConfig(idp, idp.Sequence) + return m.view.PutIDPConfig(idp, idp.Sequence, event.CreationDate) } -func (m *IDPConfig) OnError(event *models.Event, err error) error { +func (i *IDPConfig) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Nxu8s", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp config handler") - return spooler.HandleError(event, err, m.view.GetLatestIDPConfigFailedEvent, m.view.ProcessedIDPConfigFailedEvent, m.view.ProcessedIDPConfigSequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, i.view.GetLatestIDPConfigFailedEvent, i.view.ProcessedIDPConfigFailedEvent, i.view.ProcessedIDPConfigSequence, i.errorCountUntilSkip) +} + +func (i *IDPConfig) OnSuccess() error { + return spooler.HandleSuccess(i.view.UpdateIDPConfigSpoolerRunTimestamp) } diff --git a/internal/management/repository/eventsourcing/handler/idp_providers.go b/internal/management/repository/eventsourcing/handler/idp_providers.go index 56e8fbc7d2..9d873eed67 100644 --- a/internal/management/repository/eventsourcing/handler/idp_providers.go +++ b/internal/management/repository/eventsourcing/handler/idp_providers.go @@ -32,7 +32,7 @@ func (m *IDPProvider) ViewModel() string { } func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestIdpProviderSequence() + sequence, err := m.view.GetLatestIDPProviderSequence() if err != nil { return nil, err } @@ -64,7 +64,7 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { if err != nil { return err } - return m.view.DeleteIdpProvider(event.AggregateID, provider.IDPConfigID, event.Sequence) + return m.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence, event.CreationDate) case model.IDPConfigChanged, org_es_model.IDPConfigChanged: esConfig := new(iam_view_model.IDPConfigView) providerType := iam_model.IDPProviderTypeSystem @@ -72,7 +72,7 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { providerType = iam_model.IDPProviderTypeOrg } esConfig.AppendEvent(providerType, event) - providers, err := m.view.IdpProvidersByIdpConfigID(event.AggregateID, esConfig.IDPConfigID) + providers, err := m.view.IDPProvidersByIdpConfigID(event.AggregateID, esConfig.IDPConfigID) if err != nil { return err } @@ -88,16 +88,16 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { for _, provider := range providers { m.fillConfigData(provider, config) } - return m.view.PutIdpProviders(event.Sequence, providers...) + return m.view.PutIDPProviders(event.Sequence, event.CreationDate, providers...) case org_es_model.LoginPolicyRemoved: - return m.view.DeleteIdpProvidersByAggregateID(event.AggregateID, event.Sequence) + return m.view.DeleteIDPProvidersByAggregateID(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedIdpProviderSequence(event.Sequence) + return m.view.ProcessedIDPProviderSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutIdpProvider(provider, provider.Sequence) + return m.view.PutIDPProvider(provider, provider.Sequence, event.CreationDate) } func (m *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) { @@ -123,5 +123,9 @@ func (m *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, c func (m *IDPProvider) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Msj8c", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler") - return spooler.HandleError(event, err, m.view.GetLatestIdpProviderFailedEvent, m.view.ProcessedIdpProviderFailedEvent, m.view.ProcessedIdpProviderSequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, m.view.GetLatestIDPProviderFailedEvent, m.view.ProcessedIDPProviderFailedEvent, m.view.ProcessedIDPProviderSequence, m.errorCountUntilSkip) +} + +func (m *IDPProvider) OnSuccess() error { + return spooler.HandleSuccess(m.view.UpdateIDPProviderSpoolerRunTimestamp) } diff --git a/internal/management/repository/eventsourcing/handler/label_policy.go b/internal/management/repository/eventsourcing/handler/label_policy.go index 8c3238159f..2c47a03c80 100644 --- a/internal/management/repository/eventsourcing/handler/label_policy.go +++ b/internal/management/repository/eventsourcing/handler/label_policy.go @@ -53,15 +53,19 @@ func (m *LabelPolicy) processLabelPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) default: - return m.view.ProcessedLabelPolicySequence(event.Sequence) + return m.view.ProcessedLabelPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutLabelPolicy(policy, policy.Sequence) + return m.view.PutLabelPolicy(policy, policy.Sequence, event.CreationDate) } func (m *LabelPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in label policy handler") return spooler.HandleError(event, err, m.view.GetLatestLabelPolicyFailedEvent, m.view.ProcessedLabelPolicyFailedEvent, m.view.ProcessedLabelPolicySequence, m.errorCountUntilSkip) } + +func (m *LabelPolicy) OnSuccess() error { + return spooler.HandleSuccess(m.view.UpdateLabelPolicySpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/login_policy.go b/internal/management/repository/eventsourcing/handler/login_policy.go index 305953a7b7..cb6f06c4d2 100644 --- a/internal/management/repository/eventsourcing/handler/login_policy.go +++ b/internal/management/repository/eventsourcing/handler/login_policy.go @@ -57,17 +57,21 @@ func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) case model.LoginPolicyRemoved: - return m.view.DeleteLoginPolicy(event.AggregateID, event.Sequence) + return m.view.DeleteLoginPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedLoginPolicySequence(event.Sequence) + return m.view.ProcessedLoginPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutLoginPolicy(policy, policy.Sequence) + return m.view.PutLoginPolicy(policy, policy.Sequence, event.CreationDate) } func (m *LoginPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in login policy handler") return spooler.HandleError(event, err, m.view.GetLatestLoginPolicyFailedEvent, m.view.ProcessedLoginPolicyFailedEvent, m.view.ProcessedLoginPolicySequence, m.errorCountUntilSkip) } + +func (m *LoginPolicy) OnSuccess() error { + return spooler.HandleSuccess(m.view.UpdateLoginPolicySpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/machine_keys.go b/internal/management/repository/eventsourcing/handler/machine_keys.go index c09a2bdcf7..cd6b29b6a8 100644 --- a/internal/management/repository/eventsourcing/handler/machine_keys.go +++ b/internal/management/repository/eventsourcing/handler/machine_keys.go @@ -48,26 +48,30 @@ func (d *MachineKeys) processMachineKeys(event *models.Event) (err error) { case model.MachineKeyAdded: err = key.AppendEvent(event) if key.ExpirationDate.Before(time.Now()) { - return d.view.ProcessedMachineKeySequence(event.Sequence) + return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate) } case model.MachineKeyRemoved: err = key.SetData(event) if err != nil { return err } - return d.view.DeleteMachineKey(key.ID, event.Sequence) + return d.view.DeleteMachineKey(key.ID, event.Sequence, event.CreationDate) case model.UserRemoved: - return d.view.DeleteMachineKeysByUserID(event.AggregateID, event.Sequence) + return d.view.DeleteMachineKeysByUserID(event.AggregateID, event.Sequence, event.CreationDate) default: - return d.view.ProcessedMachineKeySequence(event.Sequence) + return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return d.view.PutMachineKey(key, key.Sequence) + return d.view.PutMachineKey(key, key.Sequence, event.CreationDate) } func (d *MachineKeys) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-S9fe", "id", event.AggregateID).WithError(err).Warn("something went wrong in machine key handler") return spooler.HandleError(event, err, d.view.GetLatestMachineKeyFailedEvent, d.view.ProcessedMachineKeyFailedEvent, d.view.ProcessedMachineKeySequence, d.errorCountUntilSkip) } + +func (d *MachineKeys) OnSuccess() error { + return spooler.HandleSuccess(d.view.UpdateMachineKeySpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/org.go b/internal/management/repository/eventsourcing/handler/org.go index 1674712059..23155a5c52 100644 --- a/internal/management/repository/eventsourcing/handler/org.go +++ b/internal/management/repository/eventsourcing/handler/org.go @@ -47,15 +47,19 @@ func (o *Org) Reduce(event *es_models.Event) (err error) { } err = org.AppendEvent(event) default: - return o.view.ProcessedOrgSequence(event.Sequence) + return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return o.view.PutOrg(org) + return o.view.PutOrg(org, event.CreationDate) } func (o *Org) OnError(event *es_models.Event, spoolerErr error) error { logging.LogWithFields("SPOOL-ls9ew", "id", event.AggregateID).WithError(spoolerErr).Warn("something went wrong in project app handler") return spooler.HandleError(event, spoolerErr, o.view.GetLatestOrgFailedEvent, o.view.ProcessedOrgFailedEvent, o.view.ProcessedOrgSequence, o.errorCountUntilSkip) } + +func (o *Org) OnSuccess() error { + return spooler.HandleSuccess(o.view.UpdateOrgSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/org_domain.go b/internal/management/repository/eventsourcing/handler/org_domain.go index d3c21aa63e..9dc6307749 100644 --- a/internal/management/repository/eventsourcing/handler/org_domain.go +++ b/internal/management/repository/eventsourcing/handler/org_domain.go @@ -72,7 +72,7 @@ func (d *OrgDomain) processOrgDomain(event *models.Event) (err error) { for _, existingDomain := range existingDomains { existingDomain.Primary = false } - err = d.view.PutOrgDomains(existingDomains, 0) + err = d.view.PutOrgDomains(existingDomains, 0, event.CreationDate) if err != nil { return err } @@ -82,17 +82,21 @@ func (d *OrgDomain) processOrgDomain(event *models.Event) (err error) { if err != nil { return err } - return d.view.DeleteOrgDomain(event.AggregateID, domain.Domain, event.Sequence) + return d.view.DeleteOrgDomain(event.AggregateID, domain.Domain, event.Sequence, event.CreationDate) default: - return d.view.ProcessedOrgDomainSequence(event.Sequence) + return d.view.ProcessedOrgDomainSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return d.view.PutOrgDomain(domain, domain.Sequence) + return d.view.PutOrgDomain(domain, domain.Sequence, event.CreationDate) } func (d *OrgDomain) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-us4sj", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgdomain handler") return spooler.HandleError(event, err, d.view.GetLatestOrgDomainFailedEvent, d.view.ProcessedOrgDomainFailedEvent, d.view.ProcessedOrgDomainSequence, d.errorCountUntilSkip) } + +func (o *OrgDomain) OnSuccess() error { + return spooler.HandleSuccess(o.view.UpdateOrgDomainSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/org_iam_policy.go b/internal/management/repository/eventsourcing/handler/org_iam_policy.go index 7b0b8860ca..fffe08cfec 100644 --- a/internal/management/repository/eventsourcing/handler/org_iam_policy.go +++ b/internal/management/repository/eventsourcing/handler/org_iam_policy.go @@ -53,17 +53,21 @@ func (m *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) case model.OrgIAMPolicyRemoved: - return m.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence) + return m.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedOrgIAMPolicySequence(event.Sequence) + return m.view.ProcessedOrgIAMPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutOrgIAMPolicy(policy, policy.Sequence) + return m.view.PutOrgIAMPolicy(policy, policy.Sequence, event.CreationDate) } func (m *OrgIAMPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-3Gf9s", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgIAM policy handler") return spooler.HandleError(event, err, m.view.GetLatestOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicySequence, m.errorCountUntilSkip) } + +func (o *OrgIAMPolicy) OnSuccess() error { + return spooler.HandleSuccess(o.view.UpdateOrgIAMPolicySpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/org_member.go b/internal/management/repository/eventsourcing/handler/org_member.go index c238c2363a..26f2b2fb86 100644 --- a/internal/management/repository/eventsourcing/handler/org_member.go +++ b/internal/management/repository/eventsourcing/handler/org_member.go @@ -72,14 +72,14 @@ func (m *OrgMember) processOrgMember(event *models.Event) (err error) { if err != nil { return err } - return m.view.DeleteOrgMember(event.AggregateID, member.UserID, event.Sequence) + return m.view.DeleteOrgMember(event.AggregateID, member.UserID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedOrgMemberSequence(event.Sequence) + return m.view.ProcessedOrgMemberSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutOrgMember(member, member.Sequence) + return m.view.PutOrgMember(member, member.Sequence, event.CreationDate) } func (m *OrgMember) processUser(event *models.Event) (err error) { @@ -94,7 +94,7 @@ func (m *OrgMember) processUser(event *models.Event) (err error) { return err } if len(members) == 0 { - return m.view.ProcessedOrgMemberSequence(event.Sequence) + return m.view.ProcessedOrgMemberSequence(event.Sequence, event.CreationDate) } user, err := m.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -103,11 +103,11 @@ func (m *OrgMember) processUser(event *models.Event) (err error) { for _, member := range members { m.fillUserData(member, user) } - return m.view.PutOrgMembers(members, event.Sequence) + return m.view.PutOrgMembers(members, event.Sequence, event.CreationDate) case usr_es_model.UserRemoved: - return m.view.DeleteOrgMembersByUserID(event.AggregateID, event.Sequence) + return m.view.DeleteOrgMembersByUserID(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedOrgMemberSequence(event.Sequence) + return m.view.ProcessedOrgMemberSequence(event.Sequence, event.CreationDate) } return nil } @@ -137,3 +137,7 @@ func (m *OrgMember) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-u73es", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgmember handler") return spooler.HandleError(event, err, m.view.GetLatestOrgMemberFailedEvent, m.view.ProcessedOrgMemberFailedEvent, m.view.ProcessedOrgMemberSequence, m.errorCountUntilSkip) } + +func (o *OrgMember) OnSuccess() error { + return spooler.HandleSuccess(o.view.UpdateOrgMemberSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/password_age_policy.go b/internal/management/repository/eventsourcing/handler/password_age_policy.go index ccbb1c85f9..535acf03db 100644 --- a/internal/management/repository/eventsourcing/handler/password_age_policy.go +++ b/internal/management/repository/eventsourcing/handler/password_age_policy.go @@ -53,17 +53,21 @@ func (m *PasswordAgePolicy) processPasswordAgePolicy(event *models.Event) (err e } err = policy.AppendEvent(event) case model.PasswordAgePolicyRemoved: - return m.view.DeletePasswordAgePolicy(event.AggregateID, event.Sequence) + return m.view.DeletePasswordAgePolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedPasswordAgePolicySequence(event.Sequence) + return m.view.ProcessedPasswordAgePolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutPasswordAgePolicy(policy, policy.Sequence) + return m.view.PutPasswordAgePolicy(policy, policy.Sequence, event.CreationDate) } func (m *PasswordAgePolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Bs89f", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordAge policy handler") return spooler.HandleError(event, err, m.view.GetLatestPasswordAgePolicyFailedEvent, m.view.ProcessedPasswordAgePolicyFailedEvent, m.view.ProcessedPasswordAgePolicySequence, m.errorCountUntilSkip) } + +func (m *PasswordAgePolicy) OnSuccess() error { + return spooler.HandleSuccess(m.view.UpdatePasswordAgePolicySpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/password_complexity_policy.go b/internal/management/repository/eventsourcing/handler/password_complexity_policy.go index 61020657e4..4ada8b0c95 100644 --- a/internal/management/repository/eventsourcing/handler/password_complexity_policy.go +++ b/internal/management/repository/eventsourcing/handler/password_complexity_policy.go @@ -19,12 +19,12 @@ const ( passwordComplexityPolicyTable = "management.password_complexity_policies" ) -func (m *PasswordComplexityPolicy) ViewModel() string { +func (p *PasswordComplexityPolicy) ViewModel() string { return passwordComplexityPolicyTable } -func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestPasswordComplexityPolicySequence() +func (p *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestPasswordComplexityPolicySequence() if err != nil { return nil, err } @@ -33,37 +33,41 @@ func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) { +func (p *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: - err = m.processPasswordComplexityPolicy(event) + err = p.processPasswordComplexityPolicy(event) } return err } -func (m *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) { +func (p *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) { policy := new(iam_model.PasswordComplexityPolicyView) switch event.Type { case iam_es_model.PasswordComplexityPolicyAdded, model.PasswordComplexityPolicyAdded: err = policy.AppendEvent(event) case iam_es_model.PasswordComplexityPolicyChanged, model.PasswordComplexityPolicyChanged: - policy, err = m.view.PasswordComplexityPolicyByAggregateID(event.AggregateID) + policy, err = p.view.PasswordComplexityPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) case model.PasswordComplexityPolicyRemoved: - return m.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence) + return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedPasswordComplexityPolicySequence(event.Sequence) + return p.view.ProcessedPasswordComplexityPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutPasswordComplexityPolicy(policy, policy.Sequence) + return p.view.PutPasswordComplexityPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *PasswordComplexityPolicy) OnError(event *models.Event, err error) error { +func (p *PasswordComplexityPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordComplexity policy handler") - return spooler.HandleError(event, err, m.view.GetLatestPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicySequence, p.errorCountUntilSkip) +} + +func (p *PasswordComplexityPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdatePasswordComplexityPolicySpoolerRunTimestamp) } diff --git a/internal/management/repository/eventsourcing/handler/password_lockout_policy.go b/internal/management/repository/eventsourcing/handler/password_lockout_policy.go index 0c0f1b93c0..c5a66d9528 100644 --- a/internal/management/repository/eventsourcing/handler/password_lockout_policy.go +++ b/internal/management/repository/eventsourcing/handler/password_lockout_policy.go @@ -19,12 +19,12 @@ const ( passwordLockoutPolicyTable = "management.password_lockout_policies" ) -func (m *PasswordLockoutPolicy) ViewModel() string { +func (p *PasswordLockoutPolicy) ViewModel() string { return passwordLockoutPolicyTable } -func (m *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestPasswordLockoutPolicySequence() +func (p *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestPasswordLockoutPolicySequence() if err != nil { return nil, err } @@ -33,37 +33,41 @@ func (m *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *PasswordLockoutPolicy) Reduce(event *models.Event) (err error) { +func (p *PasswordLockoutPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: - err = m.processPasswordLockoutPolicy(event) + err = p.processPasswordLockoutPolicy(event) } return err } -func (m *PasswordLockoutPolicy) processPasswordLockoutPolicy(event *models.Event) (err error) { +func (p *PasswordLockoutPolicy) processPasswordLockoutPolicy(event *models.Event) (err error) { policy := new(iam_model.PasswordLockoutPolicyView) switch event.Type { case iam_es_model.PasswordLockoutPolicyAdded, model.PasswordLockoutPolicyAdded: err = policy.AppendEvent(event) case iam_es_model.PasswordLockoutPolicyChanged, model.PasswordLockoutPolicyChanged: - policy, err = m.view.PasswordLockoutPolicyByAggregateID(event.AggregateID) + policy, err = p.view.PasswordLockoutPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) case model.PasswordLockoutPolicyRemoved: - return m.view.DeletePasswordLockoutPolicy(event.AggregateID, event.Sequence) + return p.view.DeletePasswordLockoutPolicy(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedPasswordLockoutPolicySequence(event.Sequence) + return p.view.ProcessedPasswordLockoutPolicySequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutPasswordLockoutPolicy(policy, policy.Sequence) + return p.view.PutPasswordLockoutPolicy(policy, policy.Sequence, event.CreationDate) } -func (m *PasswordLockoutPolicy) OnError(event *models.Event, err error) error { +func (p *PasswordLockoutPolicy) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Bms8f", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordLockout policy handler") - return spooler.HandleError(event, err, m.view.GetLatestPasswordLockoutPolicyFailedEvent, m.view.ProcessedPasswordLockoutPolicyFailedEvent, m.view.ProcessedPasswordLockoutPolicySequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, p.view.GetLatestPasswordLockoutPolicyFailedEvent, p.view.ProcessedPasswordLockoutPolicyFailedEvent, p.view.ProcessedPasswordLockoutPolicySequence, p.errorCountUntilSkip) +} + +func (p *PasswordLockoutPolicy) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdatePasswordLockoutPolicySpoolerRunTimestamp) } diff --git a/internal/management/repository/eventsourcing/handler/project.go b/internal/management/repository/eventsourcing/handler/project.go index 0609d175e3..0536de9ae5 100644 --- a/internal/management/repository/eventsourcing/handler/project.go +++ b/internal/management/repository/eventsourcing/handler/project.go @@ -46,17 +46,21 @@ func (p *Project) Reduce(event *models.Event) (err error) { } err = project.AppendEvent(event) case es_model.ProjectRemoved: - return p.view.DeleteProject(event.AggregateID, event.Sequence) + return p.view.DeleteProject(event.AggregateID, event.Sequence, event.CreationDate) default: - return p.view.ProcessedProjectSequence(event.Sequence) + return p.view.ProcessedProjectSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return p.view.PutProject(project) + return p.view.PutProject(project, event.CreationDate) } func (p *Project) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-dLsop3", "id", event.AggregateID).WithError(err).Warn("something went wrong in projecthandler") return spooler.HandleError(event, err, p.view.GetLatestProjectFailedEvent, p.view.ProcessedProjectFailedEvent, p.view.ProcessedProjectSequence, p.errorCountUntilSkip) } + +func (p *Project) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateProjectSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/project_grant.go b/internal/management/repository/eventsourcing/handler/project_grant.go index 3426c40022..1c7306bb21 100644 --- a/internal/management/repository/eventsourcing/handler/project_grant.go +++ b/internal/management/repository/eventsourcing/handler/project_grant.go @@ -2,6 +2,7 @@ package handler import ( "context" + "time" "github.com/caos/logging" @@ -47,7 +48,7 @@ func (p *ProjectGrant) Reduce(event *models.Event) (err error) { if err != nil { return err } - return p.updateExistingProjects(project, event.Sequence) + return p.updateExistingProjects(project, event.Sequence, event.CreationDate) case es_model.ProjectGrantAdded: err = grantedProject.AppendEvent(event) if err != nil { @@ -85,16 +86,16 @@ func (p *ProjectGrant) Reduce(event *models.Event) (err error) { if err != nil { return err } - return p.view.DeleteProjectGrant(grant.GrantID, event.Sequence) + return p.view.DeleteProjectGrant(grant.GrantID, event.Sequence, event.CreationDate) case es_model.ProjectRemoved: return p.view.DeleteProjectGrantsByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectGrantSequence(event.Sequence) + return p.view.ProcessedProjectGrantSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return p.view.PutProjectGrant(grantedProject) + return p.view.PutProjectGrant(grantedProject, event.CreationDate) } func (p *ProjectGrant) fillOrgData(grantedProject *view_model.ProjectGrantView, org, resourceOwner *org_model.Org) { @@ -106,7 +107,7 @@ func (p *ProjectGrant) getProject(projectID string) (*proj_model.Project, error) return p.projectEvents.ProjectByID(context.Background(), projectID) } -func (p *ProjectGrant) updateExistingProjects(project *view_model.ProjectView, sequence uint64) error { +func (p *ProjectGrant) updateExistingProjects(project *view_model.ProjectView, sequence uint64, eventTimestamp time.Time) error { projectGrants, err := p.view.ProjectGrantsByProjectID(project.ProjectID) if err != nil { logging.LogWithFields("SPOOL-los03", "id", project.ProjectID).WithError(err).Warn("could not update existing projects") @@ -114,10 +115,14 @@ func (p *ProjectGrant) updateExistingProjects(project *view_model.ProjectView, s for _, existingGrant := range projectGrants { existingGrant.Name = project.Name } - return p.view.PutProjectGrants(projectGrants, sequence) + return p.view.PutProjectGrants(projectGrants, sequence, eventTimestamp) } func (p *ProjectGrant) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-sQqOg", "id", event.AggregateID).WithError(err).Warn("something went wrong in granted projecthandler") return spooler.HandleError(event, err, p.view.GetLatestProjectGrantFailedEvent, p.view.ProcessedProjectGrantFailedEvent, p.view.ProcessedProjectGrantSequence, p.errorCountUntilSkip) } + +func (p *ProjectGrant) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateProjectGrantSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/project_grant_member.go b/internal/management/repository/eventsourcing/handler/project_grant_member.go index a95d83c8c4..fb37af782e 100644 --- a/internal/management/repository/eventsourcing/handler/project_grant_member.go +++ b/internal/management/repository/eventsourcing/handler/project_grant_member.go @@ -72,16 +72,16 @@ func (p *ProjectGrantMember) processProjectGrantMember(event *models.Event) (err if err != nil { return err } - return p.view.DeleteProjectGrantMember(member.GrantID, member.UserID, event.Sequence) + return p.view.DeleteProjectGrantMember(member.GrantID, member.UserID, event.Sequence, event.CreationDate) case proj_es_model.ProjectRemoved: return p.view.DeleteProjectGrantMembersByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectGrantMemberSequence(event.Sequence) + return p.view.ProcessedProjectGrantMemberSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return p.view.PutProjectGrantMember(member, member.Sequence) + return p.view.PutProjectGrantMember(member, member.Sequence, event.CreationDate) } func (p *ProjectGrantMember) processUser(event *models.Event) (err error) { @@ -96,7 +96,7 @@ func (p *ProjectGrantMember) processUser(event *models.Event) (err error) { return err } if len(members) == 0 { - return p.view.ProcessedProjectGrantMemberSequence(event.Sequence) + return p.view.ProcessedProjectGrantMemberSequence(event.Sequence, event.CreationDate) } user, err := p.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -105,9 +105,9 @@ func (p *ProjectGrantMember) processUser(event *models.Event) (err error) { for _, member := range members { p.fillUserData(member, user) } - return p.view.PutProjectGrantMembers(members, event.Sequence) + return p.view.PutProjectGrantMembers(members, event.Sequence, event.CreationDate) default: - return p.view.ProcessedProjectGrantMemberSequence(event.Sequence) + return p.view.ProcessedProjectGrantMemberSequence(event.Sequence, event.CreationDate) } return nil } @@ -138,3 +138,7 @@ func (p *ProjectGrantMember) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-kls93", "id", event.AggregateID).WithError(err).Warn("something went wrong in projectmember handler") return spooler.HandleError(event, err, p.view.GetLatestProjectGrantMemberFailedEvent, p.view.ProcessedProjectGrantMemberFailedEvent, p.view.ProcessedProjectGrantMemberSequence, p.errorCountUntilSkip) } + +func (p *ProjectGrantMember) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateProjectGrantMemberSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/project_member.go b/internal/management/repository/eventsourcing/handler/project_member.go index f5df96d10b..7de3603f25 100644 --- a/internal/management/repository/eventsourcing/handler/project_member.go +++ b/internal/management/repository/eventsourcing/handler/project_member.go @@ -72,16 +72,16 @@ func (p *ProjectMember) processProjectMember(event *models.Event) (err error) { if err != nil { return err } - return p.view.DeleteProjectMember(event.AggregateID, member.UserID, event.Sequence) + return p.view.DeleteProjectMember(event.AggregateID, member.UserID, event.Sequence, event.CreationDate) case proj_es_model.ProjectRemoved: return p.view.DeleteProjectMembersByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectMemberSequence(event.Sequence) + return p.view.ProcessedProjectMemberSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return p.view.PutProjectMember(member, member.Sequence) + return p.view.PutProjectMember(member, member.Sequence, event.CreationDate) } func (p *ProjectMember) processUser(event *models.Event) (err error) { @@ -96,7 +96,7 @@ func (p *ProjectMember) processUser(event *models.Event) (err error) { return err } if len(members) == 0 { - return p.view.ProcessedProjectMemberSequence(event.Sequence) + return p.view.ProcessedProjectMemberSequence(event.Sequence, event.CreationDate) } user, err := p.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -105,9 +105,9 @@ func (p *ProjectMember) processUser(event *models.Event) (err error) { for _, member := range members { p.fillUserData(member, user) } - return p.view.PutProjectMembers(members, event.Sequence) + return p.view.PutProjectMembers(members, event.Sequence, event.CreationDate) default: - return p.view.ProcessedProjectMemberSequence(event.Sequence) + return p.view.ProcessedProjectMemberSequence(event.Sequence, event.CreationDate) } return nil } @@ -137,3 +137,7 @@ func (p *ProjectMember) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-u73es", "id", event.AggregateID).WithError(err).Warn("something went wrong in projectmember handler") return spooler.HandleError(event, err, p.view.GetLatestProjectMemberFailedEvent, p.view.ProcessedProjectMemberFailedEvent, p.view.ProcessedProjectMemberSequence, p.errorCountUntilSkip) } + +func (p *ProjectMember) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateProjectMemberSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/project_role.go b/internal/management/repository/eventsourcing/handler/project_role.go index 54ec1f81ea..0dba4b14e8 100644 --- a/internal/management/repository/eventsourcing/handler/project_role.go +++ b/internal/management/repository/eventsourcing/handler/project_role.go @@ -52,19 +52,23 @@ func (p *ProjectRole) Reduce(event *models.Event) (err error) { if err != nil { return err } - return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event.Sequence) + return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event.Sequence, event.CreationDate) case es_model.ProjectRemoved: return p.view.DeleteProjectRolesByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectRoleSequence(event.Sequence) + return p.view.ProcessedProjectRoleSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return p.view.PutProjectRole(role) + return p.view.PutProjectRole(role, event.CreationDate) } func (p *ProjectRole) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-lso9w", "id", event.AggregateID).WithError(err).Warn("something went wrong in project role handler") return spooler.HandleError(event, err, p.view.GetLatestProjectRoleFailedEvent, p.view.ProcessedProjectRoleFailedEvent, p.view.ProcessedProjectRoleSequence, p.errorCountUntilSkip) } + +func (p *ProjectRole) OnSuccess() error { + return spooler.HandleSuccess(p.view.UpdateProjectRoleSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/user.go b/internal/management/repository/eventsourcing/handler/user.go index daf07e3f0c..7d7f53ad78 100644 --- a/internal/management/repository/eventsourcing/handler/user.go +++ b/internal/management/repository/eventsourcing/handler/user.go @@ -109,14 +109,14 @@ func (u *User) ProcessUser(event *models.Event) (err error) { } err = u.fillLoginNames(user) case es_model.UserRemoved: - return u.view.DeleteUser(event.AggregateID, event.Sequence) + return u.view.DeleteUser(event.AggregateID, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserSequence(event.Sequence) + return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return u.view.PutUser(user, user.Sequence) + return u.view.PutUser(user, user.Sequence, event.CreationDate) } func (u *User) ProcessOrg(event *models.Event) (err error) { @@ -130,7 +130,7 @@ func (u *User) ProcessOrg(event *models.Event) (err error) { case org_es_model.OrgDomainPrimarySet: return u.fillPreferredLoginNamesOnOrgUsers(event) default: - return u.view.ProcessedUserSequence(event.Sequence) + return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) } } @@ -153,7 +153,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.SetLoginNames(policy, org.Domains) } - return u.view.PutUsers(users, event.Sequence) + return u.view.PutUsers(users, event.Sequence, event.CreationDate) } func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { @@ -178,7 +178,7 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) } - return u.view.PutUsers(users, event.Sequence) + return u.view.PutUsers(users, event.Sequence, event.CreationDate) } func (u *User) fillLoginNames(user *view_model.UserView) (err error) { @@ -202,3 +202,7 @@ func (u *User) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-is8wa", "id", event.AggregateID).WithError(err).Warn("something went wrong in user handler") return spooler.HandleError(event, err, u.view.GetLatestUserFailedEvent, u.view.ProcessedUserFailedEvent, u.view.ProcessedUserSequence, u.errorCountUntilSkip) } + +func (u *User) OnSuccess() error { + return spooler.HandleSuccess(u.view.UpdateUserSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/user_external_idps.go b/internal/management/repository/eventsourcing/handler/user_external_idps.go index cfcb8f4885..de57a8f0f2 100644 --- a/internal/management/repository/eventsourcing/handler/user_external_idps.go +++ b/internal/management/repository/eventsourcing/handler/user_external_idps.go @@ -30,12 +30,12 @@ const ( externalIDPTable = "management.user_external_idps" ) -func (m *ExternalIDP) ViewModel() string { +func (i *ExternalIDP) ViewModel() string { return externalIDPTable } -func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestExternalIDPSequence() +func (i *ExternalIDP) EventQuery() (*models.SearchQuery, error) { + sequence, err := i.view.GetLatestExternalIDPSequence() if err != nil { return nil, err } @@ -44,17 +44,17 @@ func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) { LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *ExternalIDP) Reduce(event *models.Event) (err error) { +func (i *ExternalIDP) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.UserAggregate: - err = m.processUser(event) + err = i.processUser(event) case iam_es_model.IAMAggregate, org_es_model.OrgAggregate: - err = m.processIdpConfig(event) + err = i.processIdpConfig(event) } return err } -func (m *ExternalIDP) processUser(event *models.Event) (err error) { +func (i *ExternalIDP) processUser(event *models.Event) (err error) { externalIDP := new(usr_view_model.ExternalIDPView) switch event.Type { case model.HumanExternalIDPAdded: @@ -62,25 +62,25 @@ func (m *ExternalIDP) processUser(event *models.Event) (err error) { if err != nil { return err } - err = m.fillData(externalIDP) + err = i.fillData(externalIDP) case model.HumanExternalIDPRemoved, model.HumanExternalIDPCascadeRemoved: err = externalIDP.SetData(event) if err != nil { return err } - return m.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence) + return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence, event.CreationDate) case model.UserRemoved: - return m.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence) + return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedExternalIDPSequence(event.Sequence) + return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutExternalIDP(externalIDP, externalIDP.Sequence) + return i.view.PutExternalIDP(externalIDP, externalIDP.Sequence, event.CreationDate) } -func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) { +func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) { switch event.Type { case iam_es_model.IDPConfigChanged, org_es_model.IDPConfigChanged: configView := new(iam_view_model.IDPConfigView) @@ -90,45 +90,49 @@ func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) { } else { configView.AppendEvent(iam_model.IDPProviderTypeOrg, event) } - exterinalIDPs, err := m.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID) + exterinalIDPs, err := i.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID) if err != nil { return err } if event.AggregateType == iam_es_model.IAMAggregate { - config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) + config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) } else { - config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) + config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID) } if err != nil { return err } for _, provider := range exterinalIDPs { - m.fillConfigData(provider, config) + i.fillConfigData(provider, config) } - return m.view.PutExternalIDPs(event.Sequence, exterinalIDPs...) + return i.view.PutExternalIDPs(event.Sequence, event.CreationDate, exterinalIDPs...) default: - return m.view.ProcessedExternalIDPSequence(event.Sequence) + return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) } return nil } -func (m *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error { - config, err := m.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID) +func (i *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error { + config, err := i.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID) if caos_errs.IsNotFound(err) { - config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, externalIDP.IDPConfigID) + config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, externalIDP.IDPConfigID) } if err != nil { return err } - m.fillConfigData(externalIDP, config) + i.fillConfigData(externalIDP, config) return nil } -func (m *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) { +func (i *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) { externalIDP.IDPName = config.Name } -func (m *ExternalIDP) OnError(event *models.Event, err error) error { +func (i *ExternalIDP) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-4Rsu8", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler") - return spooler.HandleError(event, err, m.view.GetLatestExternalIDPFailedEvent, m.view.ProcessedExternalIDPFailedEvent, m.view.ProcessedExternalIDPSequence, m.errorCountUntilSkip) + return spooler.HandleError(event, err, i.view.GetLatestExternalIDPFailedEvent, i.view.ProcessedExternalIDPFailedEvent, i.view.ProcessedExternalIDPSequence, i.errorCountUntilSkip) +} + +func (i *ExternalIDP) OnSuccess() error { + return spooler.HandleSuccess(i.view.UpdateExternalIDPSpoolerRunTimestamp) } diff --git a/internal/management/repository/eventsourcing/handler/user_grant.go b/internal/management/repository/eventsourcing/handler/user_grant.go index e95b153299..0ffe6955ac 100644 --- a/internal/management/repository/eventsourcing/handler/user_grant.go +++ b/internal/management/repository/eventsourcing/handler/user_grant.go @@ -79,14 +79,14 @@ func (u *UserGrant) processUserGrant(event *models.Event) (err error) { } err = grant.AppendEvent(event) case grant_es_model.UserGrantRemoved, grant_es_model.UserGrantCascadeRemoved: - return u.view.DeleteUserGrant(event.AggregateID, event.Sequence) + return u.view.DeleteUserGrant(event.AggregateID, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return u.view.PutUserGrant(grant, grant.Sequence) + return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate) } func (u *UserGrant) processUser(event *models.Event) (err error) { @@ -101,7 +101,7 @@ func (u *UserGrant) processUser(event *models.Event) (err error) { return err } if len(grants) == 0 { - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } user, err := u.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -110,9 +110,9 @@ func (u *UserGrant) processUser(event *models.Event) (err error) { for _, grant := range grants { u.fillUserData(grant, user) } - return u.view.PutUserGrants(grants, event.Sequence) + return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } return nil } @@ -125,7 +125,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { return err } if len(grants) == 0 { - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } project, err := u.projectEvents.ProjectByID(context.Background(), event.AggregateID) if err != nil { @@ -134,9 +134,9 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { for _, grant := range grants { u.fillProjectData(grant, project) } - return u.view.PutUserGrants(grants, event.Sequence) + return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate) default: - return u.view.ProcessedUserGrantSequence(event.Sequence) + return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) } return nil } @@ -193,3 +193,7 @@ func (u *UserGrant) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-8is4s", "id", event.AggregateID).WithError(err).Warn("something went wrong in user handler") return spooler.HandleError(event, err, u.view.GetLatestUserGrantFailedEvent, u.view.ProcessedUserGrantFailedEvent, u.view.ProcessedUserGrantSequence, u.errorCountUntilSkip) } + +func (u *UserGrant) OnSuccess() error { + return spooler.HandleSuccess(u.view.UpdateUserGrantSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/handler/user_membership.go b/internal/management/repository/eventsourcing/handler/user_membership.go index af19ad9b81..8537905d47 100644 --- a/internal/management/repository/eventsourcing/handler/user_membership.go +++ b/internal/management/repository/eventsourcing/handler/user_membership.go @@ -73,14 +73,14 @@ func (m *UserMembership) processIam(event *models.Event) (err error) { } err = member.AppendEvent(event) case iam_es_model.IAMMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event.Sequence) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event.Sequence, event.CreationDate) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence) + return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence) + return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) } func (m *UserMembership) fillIamDisplayName(member *usr_es_model.UserMembershipView) { @@ -103,16 +103,16 @@ func (m *UserMembership) processOrg(event *models.Event) (err error) { } err = member.AppendEvent(event) case org_es_model.OrgMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence, event.CreationDate) case org_es_model.OrgChanged: return m.updateOrgDisplayName(event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence) + return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence) + return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) } func (m *UserMembership) fillOrgDisplayName(member *usr_es_model.UserMembershipView) (err error) { @@ -137,7 +137,7 @@ func (m *UserMembership) updateOrgDisplayName(event *models.Event) error { for _, membership := range memberships { membership.DisplayName = org.Name } - return m.view.BulkPutUserMemberships(memberships, event.Sequence) + return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate) } func (m *UserMembership) processProject(event *models.Event) (err error) { @@ -156,7 +156,7 @@ func (m *UserMembership) processProject(event *models.Event) (err error) { } err = member.AppendEvent(event) case proj_es_model.ProjectMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event.Sequence) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event.Sequence, event.CreationDate) case proj_es_model.ProjectGrantMemberChanged: member, err = m.view.UserMembershipByIDs(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant) if err != nil { @@ -164,20 +164,20 @@ func (m *UserMembership) processProject(event *models.Event) (err error) { } err = member.AppendEvent(event) case proj_es_model.ProjectGrantMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence, event.CreationDate) case proj_es_model.ProjectChanged: return m.updateProjectDisplayName(event) case proj_es_model.ProjectRemoved: - return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event.Sequence) + return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event.Sequence, event.CreationDate) case proj_es_model.ProjectGrantRemoved: - return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event.Sequence) + return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence) + return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence) + return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) } func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembershipView) (err error) { @@ -202,15 +202,15 @@ func (m *UserMembership) updateProjectDisplayName(event *models.Event) error { for _, membership := range memberships { membership.DisplayName = project.Name } - return m.view.BulkPutUserMemberships(memberships, event.Sequence) + return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate) } func (m *UserMembership) processUser(event *models.Event) (err error) { switch event.Type { case model.UserRemoved: - return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event.Sequence) + return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event.Sequence, event.CreationDate) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence) + return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) } } @@ -218,3 +218,7 @@ func (m *UserMembership) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-Fwer2", "id", event.AggregateID).WithError(err).Warn("something went wrong in user membership handler") return spooler.HandleError(event, err, m.view.GetLatestUserMembershipFailedEvent, m.view.ProcessedUserMembershipFailedEvent, m.view.ProcessedUserMembershipSequence, m.errorCountUntilSkip) } + +func (m *UserMembership) OnSuccess() error { + return spooler.HandleSuccess(m.view.UpdateUserMembershipSpoolerRunTimestamp) +} diff --git a/internal/management/repository/eventsourcing/view/application.go b/internal/management/repository/eventsourcing/view/application.go index 3d25e2d1d9..46672fc74a 100644 --- a/internal/management/repository/eventsourcing/view/application.go +++ b/internal/management/repository/eventsourcing/view/application.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -23,28 +24,28 @@ func (v *View) SearchApplications(request *proj_model.ApplicationSearchRequest) return view.SearchApplications(v.Db, applicationTable, request) } -func (v *View) PutApplication(app *model.ApplicationView) error { +func (v *View) PutApplication(app *model.ApplicationView, eventTimestamp time.Time) error { err := view.PutApplication(v.Db, applicationTable, app) if err != nil { return err } - return v.ProcessedApplicationSequence(app.Sequence) + return v.ProcessedApplicationSequence(app.Sequence, eventTimestamp) } -func (v *View) PutApplications(apps []*model.ApplicationView, sequence uint64) error { +func (v *View) PutApplications(apps []*model.ApplicationView, sequence uint64, eventTimestamp time.Time) error { err := view.PutApplications(v.Db, applicationTable, apps...) if err != nil { return err } - return v.ProcessedApplicationSequence(sequence) + return v.ProcessedApplicationSequence(sequence, eventTimestamp) } -func (v *View) DeleteApplication(appID string, eventSequence uint64) error { +func (v *View) DeleteApplication(appID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteApplication(v.Db, applicationTable, appID) if err != nil { return nil } - return v.ProcessedApplicationSequence(eventSequence) + return v.ProcessedApplicationSequence(eventSequence, eventTimestamp) } func (v *View) DeleteApplicationsByProjectID(projectID string) error { @@ -55,8 +56,12 @@ func (v *View) GetLatestApplicationSequence() (*repository.CurrentSequence, erro return v.latestSequence(applicationTable) } -func (v *View) ProcessedApplicationSequence(eventSequence uint64) error { - return v.saveCurrentSequence(applicationTable, eventSequence) +func (v *View) ProcessedApplicationSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(applicationTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateApplicationSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(applicationTable) } func (v *View) GetLatestApplicationFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/external_idps.go b/internal/management/repository/eventsourcing/view/external_idps.go index e7f9f9fd0b..c2944c7a5f 100644 --- a/internal/management/repository/eventsourcing/view/external_idps.go +++ b/internal/management/repository/eventsourcing/view/external_idps.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -32,45 +33,48 @@ func (v *View) SearchExternalIDPs(request *usr_model.ExternalIDPSearchRequest) ( return view.SearchExternalIDPs(v.Db, externalIDPTable, request) } -func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64) error { +func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64, eventTimestamp time.Time) error { err := view.PutExternalIDP(v.Db, externalIDPTable, externalIDP) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence) + return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) } -func (v *View) PutExternalIDPs(sequence uint64, externalIDPs ...*model.ExternalIDPView) error { +func (v *View) PutExternalIDPs(sequence uint64, eventTimestamp time.Time, externalIDPs ...*model.ExternalIDPView) error { err := view.PutExternalIDPs(v.Db, externalIDPTable, externalIDPs...) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence) + return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) } -func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64) error { +func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteExternalIDP(v.Db, externalIDPTable, externalUserID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedExternalIDPSequence(eventSequence) + return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64) error { +func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteExternalIDPsByUserID(v.Db, externalIDPTable, userID) if err != nil { return err } - return v.ProcessedExternalIDPSequence(eventSequence) + return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestExternalIDPSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(externalIDPTable) } -func (v *View) ProcessedExternalIDPSequence(eventSequence uint64) error { - return v.saveCurrentSequence(externalIDPTable, eventSequence) +func (v *View) ProcessedExternalIDPSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(externalIDPTable, eventSequence, eventTimestamp) } +func (v *View) UpdateExternalIDPSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(externalIDPTable) +} func (v *View) GetLatestExternalIDPFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { return v.latestFailedEvent(externalIDPTable, sequence) } diff --git a/internal/management/repository/eventsourcing/view/idp_configs.go b/internal/management/repository/eventsourcing/view/idp_configs.go index 6a53e228de..a9dfde45da 100644 --- a/internal/management/repository/eventsourcing/view/idp_configs.go +++ b/internal/management/repository/eventsourcing/view/idp_configs.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -20,28 +21,32 @@ func (v *View) SearchIDPConfigs(request *iam_model.IDPConfigSearchRequest) ([]*i return view.SearchIDPs(v.Db, idpConfigTable, request) } -func (v *View) PutIDPConfig(idp *iam_es_model.IDPConfigView, sequence uint64) error { +func (v *View) PutIDPConfig(idp *iam_es_model.IDPConfigView, sequence uint64, eventTimestamp time.Time) error { err := view.PutIDP(v.Db, idpConfigTable, idp) if err != nil { return err } - return v.ProcessedIDPConfigSequence(sequence) + return v.ProcessedIDPConfigSequence(sequence, eventTimestamp) } -func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64) error { +func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIDP(v.Db, idpConfigTable, idpID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPConfigSequence(eventSequence) + return v.ProcessedIDPConfigSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestIDPConfigSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(idpConfigTable) } -func (v *View) ProcessedIDPConfigSequence(eventSequence uint64) error { - return v.saveCurrentSequence(idpConfigTable, eventSequence) +func (v *View) ProcessedIDPConfigSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(idpConfigTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateIDPConfigSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(idpConfigTable) } func (v *View) GetLatestIDPConfigFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/idp_providers.go b/internal/management/repository/eventsourcing/view/idp_providers.go index def9aa78ca..207feb621f 100644 --- a/internal/management/repository/eventsourcing/view/idp_providers.go +++ b/internal/management/repository/eventsourcing/view/idp_providers.go @@ -6,68 +6,73 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( idpProviderTable = "management.idp_providers" ) -func (v *View) IdpProviderByAggregateAndIdpConfigID(aggregateID, idpConfigID string) (*model.IDPProviderView, error) { +func (v *View) IDPProviderByAggregateAndIdpConfigID(aggregateID, idpConfigID string) (*model.IDPProviderView, error) { return view.GetIDPProviderByAggregateIDAndConfigID(v.Db, idpProviderTable, aggregateID, idpConfigID) } -func (v *View) IdpProvidersByIdpConfigID(aggregateID, idpConfigID string) ([]*model.IDPProviderView, error) { +func (v *View) IDPProvidersByIdpConfigID(aggregateID, idpConfigID string) ([]*model.IDPProviderView, error) { return view.IDPProvidersByIdpConfigID(v.Db, idpProviderTable, idpConfigID) } -func (v *View) SearchIdpProviders(request *iam_model.IDPProviderSearchRequest) ([]*model.IDPProviderView, uint64, error) { +func (v *View) SearchIDPProviders(request *iam_model.IDPProviderSearchRequest) ([]*model.IDPProviderView, uint64, error) { return view.SearchIDPProviders(v.Db, idpProviderTable, request) } -func (v *View) PutIdpProvider(provider *model.IDPProviderView, sequence uint64) error { +func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64, eventTimestamp time.Time) error { err := view.PutIDPProvider(v.Db, idpProviderTable, provider) if err != nil { return err } - return v.ProcessedIdpProviderSequence(sequence) + return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) } -func (v *View) PutIdpProviders(sequence uint64, providers ...*model.IDPProviderView) error { +func (v *View) PutIDPProviders(sequence uint64, eventTimestamp time.Time, providers ...*model.IDPProviderView) error { err := view.PutIDPProviders(v.Db, idpProviderTable, providers...) if err != nil { return err } - return v.ProcessedIdpProviderSequence(sequence) + return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) } -func (v *View) DeleteIdpProvider(aggregateID, idpConfigID string, eventSequence uint64) error { +func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIDPProvider(v.Db, idpProviderTable, aggregateID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIdpProviderSequence(eventSequence) + return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteIdpProvidersByAggregateID(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteIDPProvidersByAggregateID(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteIDPProvidersByAggregateID(v.Db, idpProviderTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIdpProviderSequence(eventSequence) + return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) } -func (v *View) GetLatestIdpProviderSequence() (*global_view.CurrentSequence, error) { +func (v *View) GetLatestIDPProviderSequence() (*global_view.CurrentSequence, error) { return v.latestSequence(idpProviderTable) } -func (v *View) ProcessedIdpProviderSequence(eventSequence uint64) error { - return v.saveCurrentSequence(idpProviderTable, eventSequence) +func (v *View) ProcessedIDPProviderSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(idpProviderTable, eventSequence, eventTimestamp) } -func (v *View) GetLatestIdpProviderFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { +func (v *View) UpdateIDPProviderSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(idpProviderTable) +} + +func (v *View) GetLatestIDPProviderFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { return v.latestFailedEvent(idpProviderTable, sequence) } -func (v *View) ProcessedIdpProviderFailedEvent(failedEvent *global_view.FailedEvent) error { +func (v *View) ProcessedIDPProviderFailedEvent(failedEvent *global_view.FailedEvent) error { return v.saveFailedEvent(failedEvent) } diff --git a/internal/management/repository/eventsourcing/view/label_policies.go b/internal/management/repository/eventsourcing/view/label_policies.go index 182ca4f368..27b234fc29 100644 --- a/internal/management/repository/eventsourcing/view/label_policies.go +++ b/internal/management/repository/eventsourcing/view/label_policies.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) LabelPolicyByAggregateID(aggregateID string) (*model.LabelPolicyV return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTable, aggregateID) } -func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, sequence uint64) error { +func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy) if err != nil { return err } - return v.ProcessedLabelPolicySequence(sequence) + return v.ProcessedLabelPolicySequence(sequence, eventTimestamp) } -func (v *View) DeleteLabelPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteLabelPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteLabelPolicy(v.Db, labelPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedLabelPolicySequence(eventSequence) + return v.ProcessedLabelPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(labelPolicyTable) } -func (v *View) ProcessedLabelPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(labelPolicyTable, eventSequence) +func (v *View) ProcessedLabelPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(labelPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateLabelPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(labelPolicyTable) } func (v *View) GetLatestLabelPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/login_policies.go b/internal/management/repository/eventsourcing/view/login_policies.go index 741dbc9322..c37f4283d6 100644 --- a/internal/management/repository/eventsourcing/view/login_policies.go +++ b/internal/management/repository/eventsourcing/view/login_policies.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyV return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID) } -func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64) error { +func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutLoginPolicy(v.Db, loginPolicyTable, policy) if err != nil { return err } - return v.ProcessedLoginPolicySequence(sequence) + return v.ProcessedLoginPolicySequence(sequence, eventTimestamp) } -func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedLoginPolicySequence(eventSequence) + return v.ProcessedLoginPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestLoginPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(loginPolicyTable) } -func (v *View) ProcessedLoginPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(loginPolicyTable, eventSequence) +func (v *View) ProcessedLoginPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(loginPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateLoginPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(loginPolicyTable) } func (v *View) GetLatestLoginPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/machine_keys.go b/internal/management/repository/eventsourcing/view/machine_keys.go index 013183cc64..b037137c82 100644 --- a/internal/management/repository/eventsourcing/view/machine_keys.go +++ b/internal/management/repository/eventsourcing/view/machine_keys.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -23,39 +24,43 @@ func (v *View) SearchMachineKeys(request *usr_model.MachineKeySearchRequest) ([] return view.SearchMachineKeys(v.Db, machineKeyTable, request) } -func (v *View) PutMachineKey(org *model.MachineKeyView, sequence uint64) error { +func (v *View) PutMachineKey(org *model.MachineKeyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutMachineKey(v.Db, machineKeyTable, org) if err != nil { return err } if sequence != 0 { - return v.ProcessedMachineKeySequence(sequence) + return v.ProcessedMachineKeySequence(sequence, eventTimestamp) } return nil } -func (v *View) DeleteMachineKey(keyID string, eventSequence uint64) error { +func (v *View) DeleteMachineKey(keyID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteMachineKey(v.Db, machineKeyTable, keyID) if err != nil { return nil } - return v.ProcessedMachineKeySequence(eventSequence) + return v.ProcessedMachineKeySequence(eventSequence, eventTimestamp) } -func (v *View) DeleteMachineKeysByUserID(userID string, eventSequence uint64) error { +func (v *View) DeleteMachineKeysByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteMachineKey(v.Db, machineKeyTable, userID) if err != nil { return nil } - return v.ProcessedMachineKeySequence(eventSequence) + return v.ProcessedMachineKeySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestMachineKeySequence() (*repository.CurrentSequence, error) { return v.latestSequence(machineKeyTable) } -func (v *View) ProcessedMachineKeySequence(eventSequence uint64) error { - return v.saveCurrentSequence(machineKeyTable, eventSequence) +func (v *View) ProcessedMachineKeySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(machineKeyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateMachineKeySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(machineKeyTable) } func (v *View) GetLatestMachineKeyFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/org.go b/internal/management/repository/eventsourcing/view/org.go index 80b35435b2..a5de5fdb46 100644 --- a/internal/management/repository/eventsourcing/view/org.go +++ b/internal/management/repository/eventsourcing/view/org.go @@ -4,6 +4,7 @@ import ( org_view "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -14,12 +15,12 @@ func (v *View) OrgByID(orgID string) (*model.OrgView, error) { return org_view.OrgByID(v.Db, orgTable, orgID) } -func (v *View) PutOrg(org *model.OrgView) error { +func (v *View) PutOrg(org *model.OrgView, eventTimestamp time.Time) error { err := org_view.PutOrg(v.Db, orgTable, org) if err != nil { return err } - return v.ProcessedOrgSequence(org.Sequence) + return v.ProcessedOrgSequence(org.Sequence, eventTimestamp) } func (v *View) GetLatestOrgFailedEvent(sequence uint64) (*repository.FailedEvent, error) { @@ -30,10 +31,14 @@ func (v *View) ProcessedOrgFailedEvent(failedEvent *repository.FailedEvent) erro return v.saveFailedEvent(failedEvent) } +func (v *View) UpdateOrgSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(orgTable) +} + func (v *View) GetLatestOrgSequence() (*repository.CurrentSequence, error) { return v.latestSequence(orgTable) } -func (v *View) ProcessedOrgSequence(eventSequence uint64) error { - return v.saveCurrentSequence(orgTable, eventSequence) +func (v *View) ProcessedOrgSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(orgTable, eventSequence, eventTimestamp) } diff --git a/internal/management/repository/eventsourcing/view/org_domain.go b/internal/management/repository/eventsourcing/view/org_domain.go index 474a481d43..94f3f84c95 100644 --- a/internal/management/repository/eventsourcing/view/org_domain.go +++ b/internal/management/repository/eventsourcing/view/org_domain.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -27,39 +28,43 @@ func (v *View) SearchOrgDomains(request *org_model.OrgDomainSearchRequest) ([]*m return view.SearchOrgDomains(v.Db, orgDomainTable, request) } -func (v *View) PutOrgDomain(org *model.OrgDomainView, sequence uint64) error { +func (v *View) PutOrgDomain(org *model.OrgDomainView, sequence uint64, eventTimestamp time.Time) error { err := view.PutOrgDomain(v.Db, orgDomainTable, org) if err != nil { return err } if sequence != 0 { - return v.ProcessedOrgDomainSequence(sequence) + return v.ProcessedOrgDomainSequence(sequence, eventTimestamp) } return nil } -func (v *View) PutOrgDomains(domains []*model.OrgDomainView, sequence uint64) error { +func (v *View) PutOrgDomains(domains []*model.OrgDomainView, sequence uint64, eventTimestamp time.Time) error { err := view.PutOrgDomains(v.Db, orgDomainTable, domains...) if err != nil { return err } - return v.ProcessedUserSequence(sequence) + return v.ProcessedUserSequence(sequence, eventTimestamp) } -func (v *View) DeleteOrgDomain(orgID, domain string, eventSequence uint64) error { +func (v *View) DeleteOrgDomain(orgID, domain string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteOrgDomain(v.Db, orgDomainTable, orgID, domain) if err != nil { return nil } - return v.ProcessedOrgDomainSequence(eventSequence) + return v.ProcessedOrgDomainSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestOrgDomainSequence() (*repository.CurrentSequence, error) { return v.latestSequence(orgDomainTable) } -func (v *View) ProcessedOrgDomainSequence(eventSequence uint64) error { - return v.saveCurrentSequence(orgDomainTable, eventSequence) +func (v *View) ProcessedOrgDomainSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(orgDomainTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateOrgDomainSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(orgDomainTable) } func (v *View) GetLatestOrgDomainFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/org_iam_policy.go b/internal/management/repository/eventsourcing/view/org_iam_policy.go index 81cb67c4ac..db9d113155 100644 --- a/internal/management/repository/eventsourcing/view/org_iam_policy.go +++ b/internal/management/repository/eventsourcing/view/org_iam_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) OrgIAMPolicyByAggregateID(aggregateID string) (*model.OrgIAMPolic return view.GetOrgIAMPolicyByAggregateID(v.Db, orgIAMPolicyTable, aggregateID) } -func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64) error { +func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutOrgIAMPolicy(v.Db, orgIAMPolicyTable, policy) if err != nil { return err } - return v.ProcessedOrgIAMPolicySequence(sequence) + return v.ProcessedOrgIAMPolicySequence(sequence, eventTimestamp) } -func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteOrgIAMPolicy(v.Db, orgIAMPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedOrgIAMPolicySequence(eventSequence) + return v.ProcessedOrgIAMPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestOrgIAMPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(orgIAMPolicyTable) } -func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence) +func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateOrgIAMPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(orgIAMPolicyTable) } func (v *View) GetLatestOrgIAMPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/org_member.go b/internal/management/repository/eventsourcing/view/org_member.go index c4396d5a50..d1cb20b3c0 100644 --- a/internal/management/repository/eventsourcing/view/org_member.go +++ b/internal/management/repository/eventsourcing/view/org_member.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -23,44 +24,48 @@ func (v *View) OrgMembersByUserID(userID string) ([]*model.OrgMemberView, error) return view.OrgMembersByUserID(v.Db, orgMemberTable, userID) } -func (v *View) PutOrgMember(member *model.OrgMemberView, sequence uint64) error { +func (v *View) PutOrgMember(member *model.OrgMemberView, sequence uint64, eventTimestamp time.Time) error { err := view.PutOrgMember(v.Db, orgMemberTable, member) if err != nil { return err } - return v.ProcessedOrgMemberSequence(sequence) + return v.ProcessedOrgMemberSequence(sequence, eventTimestamp) } -func (v *View) PutOrgMembers(members []*model.OrgMemberView, sequence uint64) error { +func (v *View) PutOrgMembers(members []*model.OrgMemberView, sequence uint64, eventTimestamp time.Time) error { err := view.PutOrgMembers(v.Db, orgMemberTable, members...) if err != nil { return err } - return v.ProcessedOrgMemberSequence(sequence) + return v.ProcessedOrgMemberSequence(sequence, eventTimestamp) } -func (v *View) DeleteOrgMember(orgID, userID string, eventSequence uint64) error { +func (v *View) DeleteOrgMember(orgID, userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteOrgMember(v.Db, orgMemberTable, orgID, userID) if err != nil { return nil } - return v.ProcessedOrgMemberSequence(eventSequence) + return v.ProcessedOrgMemberSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteOrgMembersByUserID(userID string, eventSequence uint64) error { +func (v *View) DeleteOrgMembersByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteOrgMembersByUserID(v.Db, orgMemberTable, userID) if err != nil { return nil } - return v.ProcessedOrgMemberSequence(eventSequence) + return v.ProcessedOrgMemberSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestOrgMemberSequence() (*repository.CurrentSequence, error) { return v.latestSequence(orgMemberTable) } -func (v *View) ProcessedOrgMemberSequence(eventSequence uint64) error { - return v.saveCurrentSequence(orgMemberTable, eventSequence) +func (v *View) ProcessedOrgMemberSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(orgMemberTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateOrgMemberSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(orgMemberTable) } func (v *View) GetLatestOrgMemberFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/password_age_policy.go b/internal/management/repository/eventsourcing/view/password_age_policy.go index 3d6caaa8a1..e37d650072 100644 --- a/internal/management/repository/eventsourcing/view/password_age_policy.go +++ b/internal/management/repository/eventsourcing/view/password_age_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) PasswordAgePolicyByAggregateID(aggregateID string) (*model.Passwo return view.GetPasswordAgePolicyByAggregateID(v.Db, passwordAgePolicyTable, aggregateID) } -func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, sequence uint64) error { +func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutPasswordAgePolicy(v.Db, passwordAgePolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordAgePolicySequence(sequence) + return v.ProcessedPasswordAgePolicySequence(sequence, eventTimestamp) } -func (v *View) DeletePasswordAgePolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeletePasswordAgePolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeletePasswordAgePolicy(v.Db, passwordAgePolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordAgePolicySequence(eventSequence) + return v.ProcessedPasswordAgePolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestPasswordAgePolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(passwordAgePolicyTable) } -func (v *View) ProcessedPasswordAgePolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(passwordAgePolicyTable, eventSequence) +func (v *View) ProcessedPasswordAgePolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(passwordAgePolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdatePasswordAgePolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(passwordAgePolicyTable) } func (v *View) GetLatestPasswordAgePolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/password_complexity_policy.go b/internal/management/repository/eventsourcing/view/password_complexity_policy.go index 040eb1d596..70895d13a9 100644 --- a/internal/management/repository/eventsourcing/view/password_complexity_policy.go +++ b/internal/management/repository/eventsourcing/view/password_complexity_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) PasswordComplexityPolicyByAggregateID(aggregateID string) (*model return view.GetPasswordComplexityPolicyByAggregateID(v.Db, passwordComplexityPolicyTable, aggregateID) } -func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64) error { +func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutPasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordComplexityPolicySequence(sequence) + return v.ProcessedPasswordComplexityPolicySequence(sequence, eventTimestamp) } -func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeletePasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordComplexityPolicySequence(eventSequence) + return v.ProcessedPasswordComplexityPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestPasswordComplexityPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(passwordComplexityPolicyTable) } -func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence) +func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdatePasswordComplexityPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(passwordComplexityPolicyTable) } func (v *View) GetLatestPasswordComplexityPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/password_lockout_policy.go b/internal/management/repository/eventsourcing/view/password_lockout_policy.go index 099b961f57..11e3955720 100644 --- a/internal/management/repository/eventsourcing/view/password_lockout_policy.go +++ b/internal/management/repository/eventsourcing/view/password_lockout_policy.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -15,28 +16,32 @@ func (v *View) PasswordLockoutPolicyByAggregateID(aggregateID string) (*model.Pa return view.GetPasswordLockoutPolicyByAggregateID(v.Db, passwordLockoutPolicyTable, aggregateID) } -func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, sequence uint64) error { +func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, sequence uint64, eventTimestamp time.Time) error { err := view.PutPasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordLockoutPolicySequence(sequence) + return v.ProcessedPasswordLockoutPolicySequence(sequence, eventTimestamp) } -func (v *View) DeletePasswordLockoutPolicy(aggregateID string, eventSequence uint64) error { +func (v *View) DeletePasswordLockoutPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeletePasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordLockoutPolicySequence(eventSequence) + return v.ProcessedPasswordLockoutPolicySequence(eventSequence, eventTimestamp) } func (v *View) GetLatestPasswordLockoutPolicySequence() (*global_view.CurrentSequence, error) { return v.latestSequence(passwordLockoutPolicyTable) } -func (v *View) ProcessedPasswordLockoutPolicySequence(eventSequence uint64) error { - return v.saveCurrentSequence(passwordLockoutPolicyTable, eventSequence) +func (v *View) ProcessedPasswordLockoutPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(passwordLockoutPolicyTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdatePasswordLockoutPolicySpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(passwordLockoutPolicyTable) } func (v *View) GetLatestPasswordLockoutPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/project.go b/internal/management/repository/eventsourcing/view/project.go index f0f5c7d882..fede8830ee 100644 --- a/internal/management/repository/eventsourcing/view/project.go +++ b/internal/management/repository/eventsourcing/view/project.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -19,28 +20,32 @@ func (v *View) SearchProjects(request *proj_model.ProjectViewSearchRequest) ([]* return view.SearchProjects(v.Db, projectTable, request) } -func (v *View) PutProject(project *model.ProjectView) error { +func (v *View) PutProject(project *model.ProjectView, eventTimestamp time.Time) error { err := view.PutProject(v.Db, projectTable, project) if err != nil { return err } - return v.ProcessedProjectSequence(project.Sequence) + return v.ProcessedProjectSequence(project.Sequence, eventTimestamp) } -func (v *View) DeleteProject(projectID string, eventSequence uint64) error { +func (v *View) DeleteProject(projectID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteProject(v.Db, projectTable, projectID) if err != nil { return nil } - return v.ProcessedProjectSequence(eventSequence) + return v.ProcessedProjectSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestProjectSequence() (*repository.CurrentSequence, error) { return v.latestSequence(projectTable) } -func (v *View) ProcessedProjectSequence(eventSequence uint64) error { - return v.saveCurrentSequence(projectTable, eventSequence) +func (v *View) ProcessedProjectSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(projectTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateProjectSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(projectTable) } func (v *View) GetLatestProjectFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/project_grant.go b/internal/management/repository/eventsourcing/view/project_grant.go index f0cdd3330a..64f1f6272e 100644 --- a/internal/management/repository/eventsourcing/view/project_grant.go +++ b/internal/management/repository/eventsourcing/view/project_grant.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -31,28 +32,28 @@ func (v *View) SearchProjectGrants(request *proj_model.ProjectGrantViewSearchReq return view.SearchProjectGrants(v.Db, grantedProjectTable, request) } -func (v *View) PutProjectGrant(grant *model.ProjectGrantView) error { +func (v *View) PutProjectGrant(grant *model.ProjectGrantView, eventTimestamp time.Time) error { err := view.PutProjectGrant(v.Db, grantedProjectTable, grant) if err != nil { return err } - return v.ProcessedProjectGrantSequence(grant.Sequence) + return v.ProcessedProjectGrantSequence(grant.Sequence, eventTimestamp) } -func (v *View) PutProjectGrants(grants []*model.ProjectGrantView, sequence uint64) error { +func (v *View) PutProjectGrants(grants []*model.ProjectGrantView, sequence uint64, eventTimestamp time.Time) error { err := view.PutProjectGrants(v.Db, grantedProjectTable, grants...) if err != nil { return err } - return v.ProcessedProjectGrantSequence(sequence) + return v.ProcessedProjectGrantSequence(sequence, eventTimestamp) } -func (v *View) DeleteProjectGrant(grantID string, eventSequence uint64) error { +func (v *View) DeleteProjectGrant(grantID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteProjectGrant(v.Db, grantedProjectTable, grantID) if err != nil { return err } - return v.ProcessedProjectGrantSequence(eventSequence) + return v.ProcessedProjectGrantSequence(eventSequence, eventTimestamp) } func (v *View) DeleteProjectGrantsByProjectID(projectID string) error { @@ -63,8 +64,12 @@ func (v *View) GetLatestProjectGrantSequence() (*repository.CurrentSequence, err return v.latestSequence(grantedProjectTable) } -func (v *View) ProcessedProjectGrantSequence(eventSequence uint64) error { - return v.saveCurrentSequence(grantedProjectTable, eventSequence) +func (v *View) ProcessedProjectGrantSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(grantedProjectTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateProjectGrantSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(grantedProjectTable) } func (v *View) GetLatestProjectGrantFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/project_grant_member.go b/internal/management/repository/eventsourcing/view/project_grant_member.go index 39e9521a77..b9cf4391ba 100644 --- a/internal/management/repository/eventsourcing/view/project_grant_member.go +++ b/internal/management/repository/eventsourcing/view/project_grant_member.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -27,28 +28,28 @@ func (v *View) ProjectGrantMembersByUserID(userID string) ([]*model.ProjectGrant return view.ProjectGrantMembersByUserID(v.Db, projectGrantMemberTable, userID) } -func (v *View) PutProjectGrantMember(member *model.ProjectGrantMemberView, sequence uint64) error { +func (v *View) PutProjectGrantMember(member *model.ProjectGrantMemberView, sequence uint64, eventTimestamp time.Time) error { err := view.PutProjectGrantMember(v.Db, projectGrantMemberTable, member) if err != nil { return err } - return v.ProcessedProjectGrantMemberSequence(sequence) + return v.ProcessedProjectGrantMemberSequence(sequence, eventTimestamp) } -func (v *View) PutProjectGrantMembers(members []*model.ProjectGrantMemberView, sequence uint64) error { +func (v *View) PutProjectGrantMembers(members []*model.ProjectGrantMemberView, sequence uint64, eventTimestamp time.Time) error { err := view.PutProjectGrantMembers(v.Db, projectGrantMemberTable, members...) if err != nil { return err } - return v.ProcessedProjectGrantMemberSequence(sequence) + return v.ProcessedProjectGrantMemberSequence(sequence, eventTimestamp) } -func (v *View) DeleteProjectGrantMember(grantID, userID string, eventSequence uint64) error { +func (v *View) DeleteProjectGrantMember(grantID, userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteProjectGrantMember(v.Db, projectGrantMemberTable, grantID, userID) if err != nil { return nil } - return v.ProcessedProjectGrantMemberSequence(eventSequence) + return v.ProcessedProjectGrantMemberSequence(eventSequence, eventTimestamp) } func (v *View) DeleteProjectGrantMembersByProjectID(projectID string) error { @@ -59,8 +60,12 @@ func (v *View) GetLatestProjectGrantMemberSequence() (*repository.CurrentSequenc return v.latestSequence(projectGrantMemberTable) } -func (v *View) ProcessedProjectGrantMemberSequence(eventSequence uint64) error { - return v.saveCurrentSequence(projectGrantMemberTable, eventSequence) +func (v *View) ProcessedProjectGrantMemberSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(projectGrantMemberTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateProjectGrantMemberSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(projectGrantMemberTable) } func (v *View) GetLatestProjectGrantMemberFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/project_member.go b/internal/management/repository/eventsourcing/view/project_member.go index 717d827d7b..c21dee73e2 100644 --- a/internal/management/repository/eventsourcing/view/project_member.go +++ b/internal/management/repository/eventsourcing/view/project_member.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -27,28 +28,28 @@ func (v *View) ProjectMembersByUserID(userID string) ([]*model.ProjectMemberView return view.ProjectMembersByUserID(v.Db, projectMemberTable, userID) } -func (v *View) PutProjectMember(project *model.ProjectMemberView, sequence uint64) error { +func (v *View) PutProjectMember(project *model.ProjectMemberView, sequence uint64, eventTimestamp time.Time) error { err := view.PutProjectMember(v.Db, projectMemberTable, project) if err != nil { return err } - return v.ProcessedProjectMemberSequence(sequence) + return v.ProcessedProjectMemberSequence(sequence, eventTimestamp) } -func (v *View) PutProjectMembers(project []*model.ProjectMemberView, sequence uint64) error { +func (v *View) PutProjectMembers(project []*model.ProjectMemberView, sequence uint64, eventTimestamp time.Time) error { err := view.PutProjectMembers(v.Db, projectMemberTable, project...) if err != nil { return err } - return v.ProcessedProjectMemberSequence(sequence) + return v.ProcessedProjectMemberSequence(sequence, eventTimestamp) } -func (v *View) DeleteProjectMember(projectID, userID string, eventSequence uint64) error { +func (v *View) DeleteProjectMember(projectID, userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteProjectMember(v.Db, projectMemberTable, projectID, userID) if err != nil { return nil } - return v.ProcessedProjectMemberSequence(eventSequence) + return v.ProcessedProjectMemberSequence(eventSequence, eventTimestamp) } func (v *View) DeleteProjectMembersByProjectID(projectID string) error { @@ -59,8 +60,12 @@ func (v *View) GetLatestProjectMemberSequence() (*repository.CurrentSequence, er return v.latestSequence(projectMemberTable) } -func (v *View) ProcessedProjectMemberSequence(eventSequence uint64) error { - return v.saveCurrentSequence(projectMemberTable, eventSequence) +func (v *View) ProcessedProjectMemberSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(projectMemberTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateProjectMemberSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(projectMemberTable) } func (v *View) GetLatestProjectMemberFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/project_role.go b/internal/management/repository/eventsourcing/view/project_role.go index b8276471ed..6703a93efd 100644 --- a/internal/management/repository/eventsourcing/view/project_role.go +++ b/internal/management/repository/eventsourcing/view/project_role.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -31,20 +32,20 @@ func (v *View) SearchProjectRoles(request *proj_model.ProjectRoleSearchRequest) return view.SearchProjectRoles(v.Db, projectRoleTable, request) } -func (v *View) PutProjectRole(project *model.ProjectRoleView) error { +func (v *View) PutProjectRole(project *model.ProjectRoleView, eventTimestamp time.Time) error { err := view.PutProjectRole(v.Db, projectRoleTable, project) if err != nil { return err } - return v.ProcessedProjectRoleSequence(project.Sequence) + return v.ProcessedProjectRoleSequence(project.Sequence, eventTimestamp) } -func (v *View) DeleteProjectRole(projectID, orgID, key string, eventSequence uint64) error { +func (v *View) DeleteProjectRole(projectID, orgID, key string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteProjectRole(v.Db, projectRoleTable, projectID, orgID, key) if err != nil { return nil } - return v.ProcessedProjectRoleSequence(eventSequence) + return v.ProcessedProjectRoleSequence(eventSequence, eventTimestamp) } func (v *View) DeleteProjectRolesByProjectID(projectID string) error { @@ -55,8 +56,12 @@ func (v *View) GetLatestProjectRoleSequence() (*repository.CurrentSequence, erro return v.latestSequence(projectRoleTable) } -func (v *View) ProcessedProjectRoleSequence(eventSequence uint64) error { - return v.saveCurrentSequence(projectRoleTable, eventSequence) +func (v *View) ProcessedProjectRoleSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(projectRoleTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateProjectRoleSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(projectRoleTable) } func (v *View) GetLatestProjectRoleFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/sequence.go b/internal/management/repository/eventsourcing/view/sequence.go index 40d5338540..82354c98e4 100644 --- a/internal/management/repository/eventsourcing/view/sequence.go +++ b/internal/management/repository/eventsourcing/view/sequence.go @@ -2,16 +2,29 @@ package view import ( "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( sequencesTable = "management.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence) +func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimestamp time.Time) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimestamp) } func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { return repository.LatestSequence(v.Db, sequencesTable, viewName) } + +func (v *View) updateSpoolerRunSequence(viewName string) error { + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + if err != nil { + return err + } + if currentSequence.ViewName == "" { + currentSequence.ViewName = viewName + } + currentSequence.LastSuccessfulSpoolerRun = time.Now() + return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) +} diff --git a/internal/management/repository/eventsourcing/view/user.go b/internal/management/repository/eventsourcing/view/user.go index acc327a3cd..ec440e0221 100644 --- a/internal/management/repository/eventsourcing/view/user.go +++ b/internal/management/repository/eventsourcing/view/user.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -39,39 +40,43 @@ func (v *View) UserMfas(userID string) ([]*usr_model.MultiFactor, error) { return view.UserMfas(v.Db, userTable, userID) } -func (v *View) PutUsers(user []*model.UserView, sequence uint64) error { +func (v *View) PutUsers(user []*model.UserView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUsers(v.Db, userTable, user...) if err != nil { return err } - return v.ProcessedUserSequence(sequence) + return v.ProcessedUserSequence(sequence, eventTimestamp) } -func (v *View) PutUser(user *model.UserView, sequence uint64) error { +func (v *View) PutUser(user *model.UserView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUser(v.Db, userTable, user) if err != nil { return err } if sequence != 0 { - return v.ProcessedUserSequence(sequence) + return v.ProcessedUserSequence(sequence, eventTimestamp) } return nil } -func (v *View) DeleteUser(userID string, eventSequence uint64) error { +func (v *View) DeleteUser(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUser(v.Db, userTable, userID) if err != nil { return nil } - return v.ProcessedUserSequence(eventSequence) + return v.ProcessedUserSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestUserSequence() (*repository.CurrentSequence, error) { return v.latestSequence(userTable) } -func (v *View) ProcessedUserSequence(eventSequence uint64) error { - return v.saveCurrentSequence(userTable, eventSequence) +func (v *View) ProcessedUserSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(userTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateUserSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(userTable) } func (v *View) GetLatestUserFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/user_grant.go b/internal/management/repository/eventsourcing/view/user_grant.go index 29e3a2d33a..209fbfe6f4 100644 --- a/internal/management/repository/eventsourcing/view/user_grant.go +++ b/internal/management/repository/eventsourcing/view/user_grant.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/usergrant/repository/view" "github.com/caos/zitadel/internal/usergrant/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -39,36 +40,40 @@ func (v *View) UserGrantsByOrgIDAndProjectID(orgID, projectID string) ([]*model. return view.UserGrantsByOrgIDAndProjectID(v.Db, userGrantTable, orgID, projectID) } -func (v *View) PutUserGrant(grant *model.UserGrantView, sequence uint64) error { +func (v *View) PutUserGrant(grant *model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserGrant(v.Db, userGrantTable, grant) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence) + return v.ProcessedUserGrantSequence(sequence, eventTimestamp) } -func (v *View) PutUserGrants(grants []*model.UserGrantView, sequence uint64) error { +func (v *View) PutUserGrants(grants []*model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserGrants(v.Db, userGrantTable, grants...) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence) + return v.ProcessedUserGrantSequence(sequence, eventTimestamp) } -func (v *View) DeleteUserGrant(grantID string, eventSequence uint64) error { +func (v *View) DeleteUserGrant(grantID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserGrant(v.Db, userGrantTable, grantID) if err != nil { return nil } - return v.ProcessedUserGrantSequence(eventSequence) + return v.ProcessedUserGrantSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestUserGrantSequence() (*repository.CurrentSequence, error) { return v.latestSequence(userGrantTable) } -func (v *View) ProcessedUserGrantSequence(eventSequence uint64) error { - return v.saveCurrentSequence(userGrantTable, eventSequence) +func (v *View) ProcessedUserGrantSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(userGrantTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateUserGrantSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(userGrantTable) } func (v *View) GetLatestUserGrantFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/management/repository/eventsourcing/view/user_membership.go b/internal/management/repository/eventsourcing/view/user_membership.go index 8188437187..4c733dc875 100644 --- a/internal/management/repository/eventsourcing/view/user_membership.go +++ b/internal/management/repository/eventsourcing/view/user_membership.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -23,60 +24,64 @@ func (v *View) SearchUserMemberships(request *usr_model.UserMembershipSearchRequ return view.SearchUserMemberships(v.Db, userMembershipTable, request) } -func (v *View) PutUserMembership(membership *model.UserMembershipView, sequence uint64) error { +func (v *View) PutUserMembership(membership *model.UserMembershipView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserMembership(v.Db, userMembershipTable, membership) if err != nil { return err } - return v.ProcessedUserMembershipSequence(sequence) + return v.ProcessedUserMembershipSequence(sequence, eventTimestamp) } -func (v *View) BulkPutUserMemberships(memberships []*model.UserMembershipView, sequence uint64) error { +func (v *View) BulkPutUserMemberships(memberships []*model.UserMembershipView, sequence uint64, eventTimestamp time.Time) error { err := view.PutUserMemberships(v.Db, userMembershipTable, memberships...) if err != nil { return err } - return v.ProcessedUserMembershipSequence(sequence) + return v.ProcessedUserMembershipSequence(sequence, eventTimestamp) } -func (v *View) DeleteUserMembership(userID, aggregateID, objectID string, memberType usr_model.MemberType, eventSequence uint64) error { +func (v *View) DeleteUserMembership(userID, aggregateID, objectID string, memberType usr_model.MemberType, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserMembership(v.Db, userMembershipTable, userID, aggregateID, objectID, memberType) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence) + return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteUserMembershipsByUserID(userID string, eventSequence uint64) error { +func (v *View) DeleteUserMembershipsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserMembershipsByUserID(v.Db, userMembershipTable, userID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence) + return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteUserMembershipsByAggregateID(aggregateID string, eventSequence uint64) error { +func (v *View) DeleteUserMembershipsByAggregateID(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserMembershipsByAggregateID(v.Db, userMembershipTable, aggregateID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence) + return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) } -func (v *View) DeleteUserMembershipsByAggregateIDAndObjectID(aggregateID, objectID string, eventSequence uint64) error { +func (v *View) DeleteUserMembershipsByAggregateIDAndObjectID(aggregateID, objectID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteUserMembershipsByAggregateIDAndObjectID(v.Db, userMembershipTable, aggregateID, objectID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence) + return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestUserMembershipSequence() (*repository.CurrentSequence, error) { return v.latestSequence(userMembershipTable) } -func (v *View) ProcessedUserMembershipSequence(eventSequence uint64) error { - return v.saveCurrentSequence(userMembershipTable, eventSequence) +func (v *View) ProcessedUserMembershipSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(userMembershipTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateUserMembershipSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(userMembershipTable) } func (v *View) GetLatestUserMembershipFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/notification/repository/eventsourcing/handler/notification.go b/internal/notification/repository/eventsourcing/handler/notification.go index e591b2fd15..96ff4ae9ce 100644 --- a/internal/notification/repository/eventsourcing/handler/notification.go +++ b/internal/notification/repository/eventsourcing/handler/notification.go @@ -71,12 +71,12 @@ func (n *Notification) Reduce(event *models.Event) (err error) { case es_model.DomainClaimed: err = n.handleDomainClaimed(event) default: - return n.view.ProcessedNotificationSequence(event.Sequence) + return n.view.ProcessedNotificationSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return n.view.ProcessedNotificationSequence(event.Sequence) + return n.view.ProcessedNotificationSequence(event.Sequence, event.CreationDate) } func (n *Notification) handleInitUserCode(event *models.Event) (err error) { @@ -242,6 +242,10 @@ func (n *Notification) OnError(event *models.Event, err error) error { return spooler.HandleError(event, err, n.view.GetLatestNotificationFailedEvent, n.view.ProcessedNotificationFailedEvent, n.view.ProcessedNotificationSequence, n.errorCountUntilSkip) } +func (n *Notification) OnSuccess() error { + return spooler.HandleSuccess(n.view.UpdateNotificationSpoolerRunTimestamp) +} + func getSetNotifyContextData(orgID string) context.Context { return authz.SetCtxData(context.Background(), authz.CtxData{UserID: NotifyUserID, OrgID: orgID}) } diff --git a/internal/notification/repository/eventsourcing/handler/notify_user.go b/internal/notification/repository/eventsourcing/handler/notify_user.go index e05e624d39..b41cd93ce7 100644 --- a/internal/notification/repository/eventsourcing/handler/notify_user.go +++ b/internal/notification/repository/eventsourcing/handler/notify_user.go @@ -93,14 +93,14 @@ func (u *NotifyUser) ProcessUser(event *models.Event) (err error) { } u.fillLoginNames(user) case es_model.UserRemoved: - return u.view.DeleteNotifyUser(event.AggregateID, event.Sequence) + return u.view.DeleteNotifyUser(event.AggregateID, event.Sequence, event.CreationDate) default: - return u.view.ProcessedNotifyUserSequence(event.Sequence) + return u.view.ProcessedNotifyUserSequence(event.Sequence, event.CreationDate) } if err != nil { return err } - return u.view.PutNotifyUser(user, user.Sequence) + return u.view.PutNotifyUser(user, user.Sequence, event.CreationDate) } func (u *NotifyUser) ProcessOrg(event *models.Event) (err error) { @@ -114,7 +114,7 @@ func (u *NotifyUser) ProcessOrg(event *models.Event) (err error) { case org_es_model.OrgDomainPrimarySet: return u.fillPreferredLoginNamesOnOrgUsers(event) default: - return u.view.ProcessedNotifyUserSequence(event.Sequence) + return u.view.ProcessedNotifyUserSequence(event.Sequence, event.CreationDate) } } @@ -136,12 +136,12 @@ func (u *NotifyUser) fillLoginNamesOnOrgUsers(event *models.Event) error { } for _, user := range users { user.SetLoginNames(policy, org.Domains) - err := u.view.PutNotifyUser(user, 0) + err := u.view.PutNotifyUser(user, 0, event.CreationDate) if err != nil { return err } } - return u.view.ProcessedNotifyUserSequence(event.Sequence) + return u.view.ProcessedNotifyUserSequence(event.Sequence, event.CreationDate) } func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { @@ -165,7 +165,7 @@ func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *models.Event) erro } for _, user := range users { user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) - err := u.view.PutNotifyUser(user, 0) + err := u.view.PutNotifyUser(user, 0, event.CreationDate) if err != nil { return err } @@ -194,3 +194,7 @@ func (p *NotifyUser) OnError(event *models.Event, err error) error { logging.LogWithFields("SPOOL-9spwf", "id", event.AggregateID).WithError(err).Warn("something went wrong in notify user handler") return spooler.HandleError(event, err, p.view.GetLatestNotifyUserFailedEvent, p.view.ProcessedNotifyUserFailedEvent, p.view.ProcessedNotifyUserSequence, p.errorCountUntilSkip) } + +func (u *NotifyUser) OnSuccess() error { + return spooler.HandleSuccess(u.view.UpdateNotifyUserSpoolerRunTimestamp) +} diff --git a/internal/notification/repository/eventsourcing/view/notification.go b/internal/notification/repository/eventsourcing/view/notification.go index e44d019ab1..baeb75e162 100644 --- a/internal/notification/repository/eventsourcing/view/notification.go +++ b/internal/notification/repository/eventsourcing/view/notification.go @@ -2,6 +2,7 @@ package view import ( "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -12,8 +13,12 @@ func (v *View) GetLatestNotificationSequence() (*repository.CurrentSequence, err return v.latestSequence(notificationTable) } -func (v *View) ProcessedNotificationSequence(eventSequence uint64) error { - return v.saveCurrentSequence(notificationTable, eventSequence) +func (v *View) ProcessedNotificationSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(notificationTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateNotificationSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(notificationTable) } func (v *View) GetLatestNotificationFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/notification/repository/eventsourcing/view/notify_user.go b/internal/notification/repository/eventsourcing/view/notify_user.go index 1361ff1486..44d1a1e32b 100644 --- a/internal/notification/repository/eventsourcing/view/notify_user.go +++ b/internal/notification/repository/eventsourcing/view/notify_user.go @@ -4,6 +4,7 @@ import ( "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( @@ -14,13 +15,13 @@ func (v *View) NotifyUserByID(userID string) (*model.NotifyUser, error) { return view.NotifyUserByID(v.Db, notifyUserTable, userID) } -func (v *View) PutNotifyUser(user *model.NotifyUser, sequence uint64) error { +func (v *View) PutNotifyUser(user *model.NotifyUser, sequence uint64, eventTimestamp time.Time) error { err := view.PutNotifyUser(v.Db, notifyUserTable, user) if err != nil { return err } if sequence != 0 { - return v.ProcessedNotifyUserSequence(sequence) + return v.ProcessedNotifyUserSequence(sequence, eventTimestamp) } return nil } @@ -29,20 +30,24 @@ func (v *View) NotifyUsersByOrgID(orgID string) ([]*model.NotifyUser, error) { return view.NotifyUsersByOrgID(v.Db, notifyUserTable, orgID) } -func (v *View) DeleteNotifyUser(userID string, eventSequence uint64) error { +func (v *View) DeleteNotifyUser(userID string, eventSequence uint64, eventTimestamp time.Time) error { err := view.DeleteNotifyUser(v.Db, notifyUserTable, userID) if err != nil { return nil } - return v.ProcessedNotifyUserSequence(eventSequence) + return v.ProcessedNotifyUserSequence(eventSequence, eventTimestamp) } func (v *View) GetLatestNotifyUserSequence() (*repository.CurrentSequence, error) { return v.latestSequence(notifyUserTable) } -func (v *View) ProcessedNotifyUserSequence(eventSequence uint64) error { - return v.saveCurrentSequence(notifyUserTable, eventSequence) +func (v *View) ProcessedNotifyUserSequence(eventSequence uint64, eventTimestamp time.Time) error { + return v.saveCurrentSequence(notifyUserTable, eventSequence, eventTimestamp) +} + +func (v *View) UpdateNotifyUserSpoolerRunTimestamp() error { + return v.updateSpoolerRunSequence(notifyUserTable) } func (v *View) GetLatestNotifyUserFailedEvent(sequence uint64) (*repository.FailedEvent, error) { diff --git a/internal/notification/repository/eventsourcing/view/sequence.go b/internal/notification/repository/eventsourcing/view/sequence.go index 8ad083ab46..f1868e4f44 100644 --- a/internal/notification/repository/eventsourcing/view/sequence.go +++ b/internal/notification/repository/eventsourcing/view/sequence.go @@ -2,16 +2,29 @@ package view import ( "github.com/caos/zitadel/internal/view/repository" + "time" ) const ( sequencesTable = "notification.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence) +func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimestamp time.Time) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimestamp) } func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { return repository.LatestSequence(v.Db, sequencesTable, viewName) } + +func (v *View) updateSpoolerRunSequence(viewName string) error { + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + if err != nil { + return err + } + if currentSequence.ViewName == "" { + currentSequence.ViewName = viewName + } + currentSequence.LastSuccessfulSpoolerRun = time.Now() + return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) +} diff --git a/internal/telemetry/http_handler.go b/internal/telemetry/http_handler.go new file mode 100644 index 0000000000..6985791954 --- /dev/null +++ b/internal/telemetry/http_handler.go @@ -0,0 +1,33 @@ +package telemetry + +import ( + "github.com/caos/zitadel/internal/telemetry/metrics" + "net/http" + "strings" + + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" +) + +func shouldNotIgnore(endpoints ...string) func(r *http.Request) bool { + return func(r *http.Request) bool { + for _, endpoint := range endpoints { + if strings.HasPrefix(r.URL.RequestURI(), endpoint) { + return false + } + } + return true + } +} + +func TelemetryHandler(handler http.Handler, ignoredEndpoints ...string) http.Handler { + return otelhttp.NewHandler(handler, + "zitadel", + otelhttp.WithFilter(shouldNotIgnore(ignoredEndpoints...)), + otelhttp.WithPublicEndpoint(), + otelhttp.WithSpanNameFormatter(spanNameFormatter), + otelhttp.WithMeterProvider(metrics.GetMetricsProvider())) +} + +func spanNameFormatter(_ string, r *http.Request) string { + return r.Host + r.URL.EscapedPath() +} diff --git a/internal/telemetry/metrics/config/config.go b/internal/telemetry/metrics/config/config.go new file mode 100644 index 0000000000..50bfe3df47 --- /dev/null +++ b/internal/telemetry/metrics/config/config.go @@ -0,0 +1,65 @@ +package config + +import ( + "encoding/json" + + "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/telemetry/metrics" + "github.com/caos/zitadel/internal/telemetry/metrics/otel" +) + +type MetricsConfig struct { + Type string + Config metrics.Config +} + +var meter = map[string]func() metrics.Config{ + "otel": func() metrics.Config { return &otel.Config{} }, + "none": func() metrics.Config { return &NoMetrics{} }, + "": func() metrics.Config { return &NoMetrics{} }, +} + +func (c *MetricsConfig) UnmarshalJSON(data []byte) error { + var rc struct { + Type string + Config json.RawMessage + } + + if err := json.Unmarshal(data, &rc); err != nil { + return errors.ThrowInternal(err, "METER-4M9so", "error parsing config") + } + + c.Type = rc.Type + + var err error + c.Config, err = newMetricsConfig(c.Type, rc.Config) + if err != nil { + return err + } + + return c.Config.NewMetrics() +} + +func newMetricsConfig(tracerType string, configData []byte) (metrics.Config, error) { + t, ok := meter[tracerType] + if !ok { + return nil, errors.ThrowInternalf(nil, "METER-3M0ps", "config type %s not supported", tracerType) + } + + metricsConfig := t() + if len(configData) == 0 { + return metricsConfig, nil + } + + if err := json.Unmarshal(configData, metricsConfig); err != nil { + return nil, errors.ThrowInternal(err, "METER-4M9sf", "Could not read config: %v") + } + + return metricsConfig, nil +} + +type NoMetrics struct{} + +func (_ *NoMetrics) NewMetrics() error { + return nil +} diff --git a/internal/telemetry/metrics/http_handler.go b/internal/telemetry/metrics/http_handler.go new file mode 100644 index 0000000000..e9e86e1df6 --- /dev/null +++ b/internal/telemetry/metrics/http_handler.go @@ -0,0 +1,128 @@ +package metrics + +import ( + "net/http" + "strings" +) + +const ( + RequestCounter = "http.server.request_count" + RequestCountDescription = "Request counter" + TotalRequestCounter = "http.server.total_request_count" + TotalRequestDescription = "Total return code counter" + ReturnCodeCounter = "http.server.return_code_counter" + ReturnCodeCounterDescription = "Return code counter" + Method = "method" + URI = "uri" + ReturnCode = "return_code" +) + +type Handler struct { + handler http.Handler + methods []MetricType + filters []Filter +} + +type MetricType int32 + +const ( + MetricTypeTotalCount MetricType = iota + MetricTypeStatusCode + MetricTypeRequestCount +) + +type StatusRecorder struct { + http.ResponseWriter + Status int +} + +func (r *StatusRecorder) WriteHeader(status int) { + r.Status = status + r.ResponseWriter.WriteHeader(status) +} + +type Filter func(*http.Request) bool + +func NewMetricsHandler(handler http.Handler, metricMethods []MetricType, ignoredEndpoints ...string) http.Handler { + h := Handler{ + handler: handler, + methods: metricMethods, + } + if len(ignoredEndpoints) > 0 { + h.filters = append(h.filters, shouldNotIgnore(ignoredEndpoints...)) + } + return &h +} + +// ServeHTTP serves HTTP requests (http.Handler) +func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if len(h.methods) == 0 { + h.handler.ServeHTTP(w, r) + return + } + for _, f := range h.filters { + if !f(r) { + // Simply pass through to the handler if a filter rejects the request + h.handler.ServeHTTP(w, r) + return + } + } + recorder := &StatusRecorder{ + ResponseWriter: w, + Status: 200, + } + h.handler.ServeHTTP(recorder, r) + if h.containsMetricsMethod(MetricTypeRequestCount) { + RegisterRequestCounter(r) + } + if h.containsMetricsMethod(MetricTypeTotalCount) { + RegisterTotalRequestCounter(r) + } + if h.containsMetricsMethod(MetricTypeStatusCode) { + RegisterRequestCodeCounter(recorder, r) + } +} + +func (h *Handler) containsMetricsMethod(method MetricType) bool { + for _, m := range h.methods { + if m == method { + return true + } + } + return false +} + +func RegisterRequestCounter(r *http.Request) { + var labels = map[string]interface{}{ + URI: strings.Split(r.RequestURI, "?")[0], + Method: r.Method, + } + RegisterCounter(RequestCounter, RequestCountDescription) + AddCount(r.Context(), RequestCounter, 1, labels) +} + +func RegisterTotalRequestCounter(r *http.Request) { + RegisterCounter(TotalRequestCounter, TotalRequestDescription) + AddCount(r.Context(), TotalRequestCounter, 1, nil) +} + +func RegisterRequestCodeCounter(recorder *StatusRecorder, r *http.Request) { + var labels = map[string]interface{}{ + URI: strings.Split(r.RequestURI, "?")[0], + Method: r.Method, + ReturnCode: recorder.Status, + } + RegisterCounter(ReturnCodeCounter, ReturnCodeCounterDescription) + AddCount(r.Context(), ReturnCodeCounter, 1, labels) +} + +func shouldNotIgnore(endpoints ...string) func(r *http.Request) bool { + return func(r *http.Request) bool { + for _, endpoint := range endpoints { + if strings.HasPrefix(r.URL.RequestURI(), endpoint) { + return false + } + } + return true + } +} diff --git a/internal/telemetry/metrics/metrics.go b/internal/telemetry/metrics/metrics.go new file mode 100644 index 0000000000..4dc3b0675d --- /dev/null +++ b/internal/telemetry/metrics/metrics.go @@ -0,0 +1,73 @@ +package metrics + +import ( + "context" + "go.opentelemetry.io/otel/api/metric" + "net/http" +) + +const ( + ActiveSessionCounter = "zitadel.active_session_counter" + ActiveSessionCounterDescription = "Active session counter" + SpoolerDivCounter = "zitadel.spooler_div_milliseconds" + SpoolerDivCounterDescription = "Spooler div from last successful run to now in milliseconds" + Database = "database" + ViewName = "view_name" +) + +type Metrics interface { + GetExporter() http.Handler + GetMetricsProvider() metric.MeterProvider + RegisterCounter(name, description string) error + AddCount(ctx context.Context, name string, value int64, labels map[string]interface{}) error + RegisterUpDownSumObserver(name, description string, callbackFunc metric.Int64ObserverFunc) error + RegisterValueObserver(name, description string, callbackFunc metric.Int64ObserverFunc) error +} + +type Config interface { + NewMetrics() error +} + +var M Metrics + +func GetExporter() http.Handler { + if M == nil { + return nil + } + return M.GetExporter() +} + +func GetMetricsProvider() metric.MeterProvider { + if M == nil { + return nil + } + return M.GetMetricsProvider() +} + +func RegisterCounter(name, description string) error { + if M == nil { + return nil + } + return M.RegisterCounter(name, description) +} + +func AddCount(ctx context.Context, name string, value int64, labels map[string]interface{}) error { + if M == nil { + return nil + } + return M.AddCount(ctx, name, value, labels) +} + +func RegisterUpDownSumObserver(name, description string, callbackFunc metric.Int64ObserverFunc) error { + if M == nil { + return nil + } + return M.RegisterUpDownSumObserver(name, description, callbackFunc) +} + +func RegisterValueObserver(name, description string, callbackFunc metric.Int64ObserverFunc) error { + if M == nil { + return nil + } + return M.RegisterValueObserver(name, description, callbackFunc) +} diff --git a/internal/telemetry/metrics/otel/config.go b/internal/telemetry/metrics/otel/config.go new file mode 100644 index 0000000000..8d6718d319 --- /dev/null +++ b/internal/telemetry/metrics/otel/config.go @@ -0,0 +1,14 @@ +package otel + +import ( + "github.com/caos/zitadel/internal/telemetry/metrics" +) + +type Config struct { + MeterName string +} + +func (c *Config) NewMetrics() (err error) { + metrics.M, err = NewMetrics(c.MeterName) + return err +} diff --git a/internal/telemetry/metrics/otel/open_telemetry.go b/internal/telemetry/metrics/otel/open_telemetry.go new file mode 100644 index 0000000000..80e04f5ce2 --- /dev/null +++ b/internal/telemetry/metrics/otel/open_telemetry.go @@ -0,0 +1,92 @@ +package otel + +import ( + "context" + caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/telemetry/metrics" + "go.opentelemetry.io/otel/api/metric" + "go.opentelemetry.io/otel/exporters/metric/prometheus" + "go.opentelemetry.io/otel/label" + "net/http" + "sync" +) + +type Metrics struct { + Exporter *prometheus.Exporter + Meter metric.Meter + Counters sync.Map + UpDownSumObserver sync.Map + ValueObservers sync.Map +} + +func NewMetrics(meterName string) (metrics.Metrics, error) { + exporter, err := prometheus.NewExportPipeline( + prometheus.Config{}, + ) + if err != nil { + return &Metrics{}, err + } + return &Metrics{ + Exporter: exporter, + Meter: exporter.MeterProvider().Meter(meterName), + }, nil +} + +func (m *Metrics) GetExporter() http.Handler { + return m.Exporter +} + +func (m *Metrics) GetMetricsProvider() metric.MeterProvider { + return m.Exporter.MeterProvider() +} + +func (m *Metrics) RegisterCounter(name, description string) error { + if _, exists := m.Counters.Load(name); exists { + return nil + } + counter := metric.Must(m.Meter).NewInt64Counter(name, metric.WithDescription(description)) + m.Counters.Store(name, counter) + return nil +} + +func (m *Metrics) AddCount(ctx context.Context, name string, value int64, labels map[string]interface{}) error { + counter, exists := m.Counters.Load(name) + if !exists { + return caos_errs.ThrowNotFound(nil, "METER-4u8fs", "Errors.Metrics.Counter.NotFound") + } + counter.(metric.Int64Counter).Add(ctx, value, MapToKeyValue(labels)...) + return nil +} + +func (m *Metrics) RegisterUpDownSumObserver(name, description string, callbackFunc metric.Int64ObserverFunc) error { + if _, exists := m.UpDownSumObserver.Load(name); exists { + return nil + } + sumObserver := metric.Must(m.Meter).NewInt64UpDownSumObserver( + name, callbackFunc, metric.WithDescription(description)) + + m.UpDownSumObserver.Store(name, sumObserver) + return nil +} + +func (m *Metrics) RegisterValueObserver(name, description string, callbackFunc metric.Int64ObserverFunc) error { + if _, exists := m.UpDownSumObserver.Load(name); exists { + return nil + } + sumObserver := metric.Must(m.Meter).NewInt64ValueObserver( + name, callbackFunc, metric.WithDescription(description)) + + m.UpDownSumObserver.Store(name, sumObserver) + return nil +} + +func MapToKeyValue(labels map[string]interface{}) []label.KeyValue { + if labels == nil { + return nil + } + keyValues := make([]label.KeyValue, 0, len(labels)) + for key, value := range labels { + keyValues = append(keyValues, label.Any(key, value)) + } + return keyValues +} diff --git a/internal/tracing/caller.go b/internal/telemetry/tracing/caller.go similarity index 100% rename from internal/tracing/caller.go rename to internal/telemetry/tracing/caller.go diff --git a/internal/tracing/config/config.go b/internal/telemetry/tracing/config/config.go similarity index 86% rename from internal/tracing/config/config.go rename to internal/telemetry/tracing/config/config.go index 977f8f9057..70a08be426 100644 --- a/internal/tracing/config/config.go +++ b/internal/telemetry/tracing/config/config.go @@ -4,10 +4,10 @@ import ( "encoding/json" "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/tracing" - "github.com/caos/zitadel/internal/tracing/google" - "github.com/caos/zitadel/internal/tracing/log" - "github.com/caos/zitadel/internal/tracing/otel" + "github.com/caos/zitadel/internal/telemetry/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing/google" + "github.com/caos/zitadel/internal/telemetry/tracing/log" + "github.com/caos/zitadel/internal/telemetry/tracing/otel" ) type TracingConfig struct { diff --git a/internal/tracing/google/google_tracer.go b/internal/telemetry/tracing/google/google_tracer.go similarity index 89% rename from internal/tracing/google/google_tracer.go rename to internal/telemetry/tracing/google/google_tracer.go index ba57958730..35754a284e 100644 --- a/internal/tracing/google/google_tracer.go +++ b/internal/telemetry/tracing/google/google_tracer.go @@ -6,8 +6,8 @@ import ( texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace" "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/tracing" - "github.com/caos/zitadel/internal/tracing/otel" + "github.com/caos/zitadel/internal/telemetry/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing/otel" sdk_trace "go.opentelemetry.io/otel/sdk/trace" ) diff --git a/internal/tracing/log/config.go b/internal/telemetry/tracing/log/config.go similarity index 82% rename from internal/tracing/log/config.go rename to internal/telemetry/tracing/log/config.go index c903a46f14..6fd34559b6 100644 --- a/internal/tracing/log/config.go +++ b/internal/telemetry/tracing/log/config.go @@ -1,8 +1,8 @@ package log import ( - "github.com/caos/zitadel/internal/tracing" - "github.com/caos/zitadel/internal/tracing/otel" + "github.com/caos/zitadel/internal/telemetry/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing/otel" "go.opentelemetry.io/otel/exporters/stdout" sdk_trace "go.opentelemetry.io/otel/sdk/trace" ) diff --git a/internal/tracing/otel/config.go b/internal/telemetry/tracing/otel/config.go similarity index 90% rename from internal/tracing/otel/config.go rename to internal/telemetry/tracing/otel/config.go index 6f0087dc13..9aa7d43d63 100644 --- a/internal/tracing/otel/config.go +++ b/internal/telemetry/tracing/otel/config.go @@ -1,7 +1,7 @@ package otel import ( - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" "go.opentelemetry.io/otel/exporters/otlp" sdk_trace "go.opentelemetry.io/otel/sdk/trace" ) diff --git a/internal/tracing/otel/open_telemetry.go b/internal/telemetry/tracing/otel/open_telemetry.go similarity index 97% rename from internal/tracing/otel/open_telemetry.go rename to internal/telemetry/tracing/otel/open_telemetry.go index 12e7b82e72..4524cd0424 100644 --- a/internal/tracing/otel/open_telemetry.go +++ b/internal/telemetry/tracing/otel/open_telemetry.go @@ -4,7 +4,7 @@ import ( "context" "net/http" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" "go.opentelemetry.io/otel/api/global" api_trace "go.opentelemetry.io/otel/api/trace" "go.opentelemetry.io/otel/propagators" diff --git a/internal/tracing/span.go b/internal/telemetry/tracing/span.go similarity index 100% rename from internal/tracing/span.go rename to internal/telemetry/tracing/span.go diff --git a/internal/tracing/tracing.go b/internal/telemetry/tracing/tracing.go similarity index 100% rename from internal/tracing/tracing.go rename to internal/telemetry/tracing/tracing.go diff --git a/internal/tracing/http_handler.go b/internal/tracing/http_handler.go deleted file mode 100644 index 38c9664a70..0000000000 --- a/internal/tracing/http_handler.go +++ /dev/null @@ -1,31 +0,0 @@ -package tracing - -import ( - "net/http" - "strings" - - http_trace "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" -) - -func shouldNotIgnore(endpoints ...string) func(r *http.Request) bool { - return func(r *http.Request) bool { - for _, endpoint := range endpoints { - if strings.HasPrefix(r.URL.RequestURI(), endpoint) { - return false - } - } - return true - } -} - -func TraceHandler(handler http.Handler, ignoredEndpoints ...string) http.Handler { - return http_trace.NewHandler(handler, - "zitadel", - http_trace.WithFilter(shouldNotIgnore(ignoredEndpoints...)), - http_trace.WithPublicEndpoint(), - http_trace.WithSpanNameFormatter(spanNameFormatter)) -} - -func spanNameFormatter(_ string, r *http.Request) string { - return r.Host + r.URL.EscapedPath() -} diff --git a/internal/ui/login/handler/login.go b/internal/ui/login/handler/login.go index 149167c418..22495627a9 100644 --- a/internal/ui/login/handler/login.go +++ b/internal/ui/login/handler/login.go @@ -82,7 +82,7 @@ func CreateLogin(config Config, authRepo *eventsourcing.EsRepository, systemDefa security := middleware.SecurityHeaders(csp(), login.cspErrorHandler) userAgentCookie, err := middleware.NewUserAgentHandler(config.UserAgentCookieConfig, id.SonyFlakeGenerator, localDevMode) logging.Log("CONFI-Dvwf2").OnError(err).Panic("unable to create userAgentInterceptor") - login.router = CreateRouter(login, statikFS, csrf, cache, security, userAgentCookie, middleware.TraceHandler(EndpointResources)) + login.router = CreateRouter(login, statikFS, csrf, cache, security, userAgentCookie, middleware.TelemetryHandler(EndpointResources)) login.renderer = CreateRenderer(prefix, statikFS, config.LanguageCookieName, config.DefaultLanguage) login.parser = form.NewParser() return login, handlerPrefix diff --git a/internal/user/repository/eventsourcing/eventstore.go b/internal/user/repository/eventsourcing/eventstore.go index 05a60c85d3..9fce4c30dc 100644 --- a/internal/user/repository/eventsourcing/eventstore.go +++ b/internal/user/repository/eventsourcing/eventstore.go @@ -21,7 +21,7 @@ import ( iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/id" global_model "github.com/caos/zitadel/internal/model" - "github.com/caos/zitadel/internal/tracing" + "github.com/caos/zitadel/internal/telemetry/tracing" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" ) diff --git a/internal/user/repository/view/user_session_view.go b/internal/user/repository/view/user_session_view.go index 156a4d705f..930559af26 100644 --- a/internal/user/repository/view/user_session_view.go +++ b/internal/user/repository/view/user_session_view.go @@ -1,6 +1,7 @@ package view import ( + auth_model "github.com/caos/zitadel/internal/auth_request/model" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/view/repository" "github.com/jinzhu/gorm" @@ -58,6 +59,20 @@ func UserSessionsByAgentID(db *gorm.DB, table, agentID string) ([]*model.UserSes return userSessions, err } +func ActiveUserSessions(db *gorm.DB, table string) ([]*model.UserSessionView, error) { + userSessions := make([]*model.UserSessionView, 0) + activeQuery := &usr_model.UserSessionSearchQuery{ + Key: usr_model.UserSessionSearchKeyState, + Method: global_model.SearchMethodEquals, + Value: auth_model.UserSessionStateActive, + } + query := repository.PrepareSearchQuery(table, model.UserSessionSearchRequest{ + Queries: []*usr_model.UserSessionSearchQuery{activeQuery}, + }) + _, err := query(db, &userSessions) + return userSessions, err +} + func PutUserSession(db *gorm.DB, table string, session *model.UserSessionView) error { save := repository.PrepareSave(table) return save(db, session) diff --git a/internal/view/model/view.go b/internal/view/model/view.go index 109a35e186..6f766b912b 100644 --- a/internal/view/model/view.go +++ b/internal/view/model/view.go @@ -5,8 +5,9 @@ import ( ) type View struct { - Database string - ViewName string - CurrentSequence uint64 - CurrentTimestamp time.Time + Database string + ViewName string + CurrentSequence uint64 + EventTimestamp time.Time + LastSuccessfulSpoolerRun time.Time } diff --git a/internal/view/repository/failed_events.go b/internal/view/repository/failed_events.go index 8c3551702b..404aa58d8d 100644 --- a/internal/view/repository/failed_events.go +++ b/internal/view/repository/failed_events.go @@ -84,7 +84,7 @@ func SaveFailedEvent(db *gorm.DB, table string, failedEvent *FailedEvent) error err := save(db, failedEvent) if err != nil { - return errors.ThrowInternal(err, "VIEW-5kOhP", "unable to updated failed events") + return errors.ThrowInternal(err, "VIEW-4F8us", "unable to updated failed events") } return nil } diff --git a/internal/view/repository/sequence.go b/internal/view/repository/sequence.go index 1491c39642..10023b2b66 100644 --- a/internal/view/repository/sequence.go +++ b/internal/view/repository/sequence.go @@ -9,9 +9,10 @@ import ( ) type CurrentSequence struct { - ViewName string `gorm:"column:view_name;primary_key"` - CurrentSequence uint64 `gorm:"column:current_sequence"` - CurrentTimestamp time.Time `gorm:"column:timestamp"` + ViewName string `gorm:"column:view_name;primary_key"` + CurrentSequence uint64 `gorm:"column:current_sequence"` + EventTimestamp time.Time `gorm:"column:event_timestamp"` + LastSuccessfulSpoolerRun time.Time `gorm:"column:last_successful_spooler_run"` } type SequenceSearchKey int32 @@ -35,16 +36,21 @@ func (key sequenceSearchKey) ToColumnName() string { func CurrentSequenceToModel(sequence *CurrentSequence) *model.View { dbView := strings.Split(sequence.ViewName, ".") return &model.View{ - Database: dbView[0], - ViewName: dbView[1], - CurrentSequence: sequence.CurrentSequence, - CurrentTimestamp: sequence.CurrentTimestamp, + Database: dbView[0], + ViewName: dbView[1], + CurrentSequence: sequence.CurrentSequence, + EventTimestamp: sequence.EventTimestamp, + LastSuccessfulSpoolerRun: sequence.LastSuccessfulSpoolerRun, } } -func SaveCurrentSequence(db *gorm.DB, table, viewName string, sequence uint64) error { +func SaveCurrentSequence(db *gorm.DB, table, viewName string, sequence uint64, eventTimestamp time.Time) error { + return UpdateCurrentSequence(db, table, &CurrentSequence{viewName, sequence, eventTimestamp, time.Now()}) +} + +func UpdateCurrentSequence(db *gorm.DB, table string, currentSequence *CurrentSequence) error { save := PrepareSave(table) - err := save(db, &CurrentSequence{viewName, sequence, time.Now()}) + err := save(db, currentSequence) if err != nil { return caos_errs.ThrowInternal(err, "VIEW-5kOhP", "unable to updated processed sequence") @@ -83,5 +89,5 @@ func ClearView(db *gorm.DB, truncateView, sequenceTable string) error { if err != nil { return err } - return SaveCurrentSequence(db, sequenceTable, truncateView, 0) + return SaveCurrentSequence(db, sequenceTable, truncateView, 0, time.Now()) } diff --git a/migrations/cockroach/V1.24__current_sequence.sql b/migrations/cockroach/V1.24__current_sequence.sql new file mode 100644 index 0000000000..6d937598f9 --- /dev/null +++ b/migrations/cockroach/V1.24__current_sequence.sql @@ -0,0 +1,11 @@ +ALTER TABLE management.current_sequences ADD COLUMN last_successful_spooler_run TIMESTAMPTZ; +ALTER TABLE auth.current_sequences ADD COLUMN last_successful_spooler_run TIMESTAMPTZ; +ALTER TABLE authz.current_sequences ADD COLUMN last_successful_spooler_run TIMESTAMPTZ; +ALTER TABLE adminapi.current_sequences ADD COLUMN last_successful_spooler_run TIMESTAMPTZ; +ALTER TABLE notification.current_sequences ADD COLUMN last_successful_spooler_run TIMESTAMPTZ; + +ALTER TABLE management.current_sequences RENAME COLUMN timestamp TO event_timestamp; +ALTER TABLE auth.current_sequences RENAME COLUMN timestamp TO event_timestamp; +ALTER TABLE authz.current_sequences RENAME COLUMN timestamp TO event_timestamp; +ALTER TABLE adminapi.current_sequences RENAME COLUMN timestamp TO event_timestamp; +ALTER TABLE notification.current_sequences RENAME COLUMN timestamp TO event_timestamp; diff --git a/pkg/grpc/admin/proto/admin.proto b/pkg/grpc/admin/proto/admin.proto index 3e0b685a0c..fa4677c1cc 100644 --- a/pkg/grpc/admin/proto/admin.proto +++ b/pkg/grpc/admin/proto/admin.proto @@ -853,7 +853,8 @@ message View { string database = 1; string view_name = 2; uint64 processed_sequence = 3; - google.protobuf.Timestamp view_timestamp = 4; + google.protobuf.Timestamp event_timestamp = 4; + google.protobuf.Timestamp last_successful_spooler_run = 5; } message IdpID {