mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 19:07:30 +00:00
feat: call webhooks at least once (#5454)
* feat: call webhooks at least once * self review * feat: improve notification observability * feat: add notification tracing * test(e2e): test at-least-once webhook delivery * fix webhook notifications * dedicated quota notifications handler * fix linting * fix e2e test * wait less in e2e test * fix: don't ignore failed events in handlers * fix: don't ignore failed events in handlers * faster requeues * question * fix retries * fix retries * retry * don't instance ids query * revert handler_projection * statements can be nil * cleanup * make unit tests pass * add comments * add comments * lint * spool only active instances * feat(config): handle inactive instances * customizable HandleInactiveInstances * call inactive instances quota webhooks * test: handling with and w/o inactive instances * omit retrying noop statements * docs: describe projection options * enable global handling of inactive instances * self review * requeue quota notifications every 5m * remove caos_errors reference * fix comment styles * make handlers package flat * fix linting * fix repeating quota notifications * test with more usage * debug log channel init failures
This commit is contained in:
77
internal/notification/projections.go
Normal file
77
internal/notification/projections.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package notification
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
statik_fs "github.com/rakyll/statik/fs"
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/notification/handlers"
|
||||
_ "github.com/zitadel/zitadel/internal/notification/statik"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/query/projection"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
metricSuccessfulDeliveriesEmail = "successful_deliveries_email"
|
||||
metricFailedDeliveriesEmail = "failed_deliveries_email"
|
||||
metricSuccessfulDeliveriesSMS = "successful_deliveries_sms"
|
||||
metricFailedDeliveriesSMS = "failed_deliveries_sms"
|
||||
metricSuccessfulDeliveriesJSON = "successful_deliveries_json"
|
||||
metricFailedDeliveriesJSON = "failed_deliveries_json"
|
||||
)
|
||||
|
||||
func Start(
|
||||
ctx context.Context,
|
||||
userHandlerCustomConfig projection.CustomConfig,
|
||||
quotaHandlerCustomConfig projection.CustomConfig,
|
||||
externalPort uint16,
|
||||
externalSecure bool,
|
||||
commands *command.Commands,
|
||||
queries *query.Queries,
|
||||
es *eventstore.Eventstore,
|
||||
assetsPrefix func(context.Context) string,
|
||||
fileSystemPath string,
|
||||
userEncryption,
|
||||
smtpEncryption,
|
||||
smsEncryption crypto.EncryptionAlgorithm,
|
||||
) {
|
||||
statikFS, err := statik_fs.NewWithNamespace("notification")
|
||||
logging.OnError(err).Panic("unable to start listener")
|
||||
err = metrics.RegisterCounter(metricSuccessfulDeliveriesEmail, "Successfully delivered emails")
|
||||
logging.WithFields("metric", metricSuccessfulDeliveriesEmail).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricFailedDeliveriesEmail, "Failed email deliveries")
|
||||
logging.WithFields("metric", metricFailedDeliveriesEmail).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricSuccessfulDeliveriesSMS, "Successfully delivered SMS")
|
||||
logging.WithFields("metric", metricSuccessfulDeliveriesSMS).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricFailedDeliveriesSMS, "Failed SMS deliveries")
|
||||
logging.WithFields("metric", metricFailedDeliveriesSMS).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricSuccessfulDeliveriesJSON, "Successfully delivered JSON messages")
|
||||
logging.WithFields("metric", metricSuccessfulDeliveriesJSON).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricFailedDeliveriesJSON, "Failed JSON message deliveries")
|
||||
logging.WithFields("metric", metricFailedDeliveriesJSON).OnError(err).Panic("unable to register counter")
|
||||
q := handlers.NewNotificationQueries(queries, es, externalPort, externalSecure, fileSystemPath, userEncryption, smtpEncryption, smsEncryption, statikFS)
|
||||
handlers.NewUserNotifier(
|
||||
ctx,
|
||||
projection.ApplyCustomConfig(userHandlerCustomConfig),
|
||||
commands,
|
||||
q,
|
||||
assetsPrefix,
|
||||
metricSuccessfulDeliveriesEmail,
|
||||
metricFailedDeliveriesEmail,
|
||||
metricSuccessfulDeliveriesSMS,
|
||||
metricFailedDeliveriesSMS,
|
||||
).Start()
|
||||
handlers.NewQuotaNotifier(
|
||||
ctx,
|
||||
projection.ApplyCustomConfig(quotaHandlerCustomConfig),
|
||||
commands,
|
||||
q,
|
||||
metricSuccessfulDeliveriesJSON,
|
||||
metricFailedDeliveriesJSON,
|
||||
).Start()
|
||||
}
|
Reference in New Issue
Block a user