mirror of
https://github.com/minio/minio.git
synced 2025-11-10 05:59:43 -05:00
Add an option to make bucket notifications synchronous (#17406)
With the current asynchronous behaviour in sending notification events to the targets, we can't provide guaranteed delivery as the systems might go for restarts. For such event-driven use-cases, we can provide an option to enable synchronous events where the APIs wait until the event is successfully sent or persisted. This commit adds 'MINIO_API_SYNC_EVENTS' env which when set to 'on' will enable sending/persisting events to targets synchronously.
This commit is contained in:
@@ -35,20 +35,18 @@ import (
|
||||
// EventNotifier - notifies external systems about events in MinIO.
|
||||
type EventNotifier struct {
|
||||
sync.RWMutex
|
||||
targetList *event.TargetList
|
||||
targetResCh chan event.TargetIDResult
|
||||
bucketRulesMap map[string]event.RulesMap
|
||||
bucketRemoteTargetRulesMap map[string]map[event.TargetID]event.RulesMap
|
||||
targetList *event.TargetList
|
||||
targetResCh chan event.TargetIDResult
|
||||
bucketRulesMap map[string]event.RulesMap
|
||||
}
|
||||
|
||||
// NewEventNotifier - creates new event notification object.
|
||||
func NewEventNotifier() *EventNotifier {
|
||||
// targetList/bucketRulesMap/bucketRemoteTargetRulesMap are populated by NotificationSys.InitBucketTargets()
|
||||
return &EventNotifier{
|
||||
targetList: event.NewTargetList(),
|
||||
targetResCh: make(chan event.TargetIDResult),
|
||||
bucketRulesMap: make(map[string]event.RulesMap),
|
||||
bucketRemoteTargetRulesMap: make(map[string]map[event.TargetID]event.RulesMap),
|
||||
targetList: event.NewTargetList(),
|
||||
targetResCh: make(chan event.TargetIDResult),
|
||||
bucketRulesMap: make(map[string]event.RulesMap),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,10 +120,6 @@ func (evnot *EventNotifier) AddRulesMap(bucketName string, rulesMap event.RulesM
|
||||
|
||||
rulesMap = rulesMap.Clone()
|
||||
|
||||
for _, targetRulesMap := range evnot.bucketRemoteTargetRulesMap[bucketName] {
|
||||
rulesMap.Add(targetRulesMap)
|
||||
}
|
||||
|
||||
// Do not add for an empty rulesMap.
|
||||
if len(rulesMap) == 0 {
|
||||
delete(evnot.bucketRulesMap, bucketName)
|
||||
@@ -174,29 +168,18 @@ func (evnot *EventNotifier) RemoveNotification(bucketName string) {
|
||||
defer evnot.Unlock()
|
||||
|
||||
delete(evnot.bucketRulesMap, bucketName)
|
||||
|
||||
targetIDSet := event.NewTargetIDSet()
|
||||
for targetID := range evnot.bucketRemoteTargetRulesMap[bucketName] {
|
||||
targetIDSet[targetID] = struct{}{}
|
||||
delete(evnot.bucketRemoteTargetRulesMap[bucketName], targetID)
|
||||
}
|
||||
evnot.targetList.Remove(targetIDSet)
|
||||
|
||||
delete(evnot.bucketRemoteTargetRulesMap, bucketName)
|
||||
}
|
||||
|
||||
// RemoveAllRemoteTargets - closes and removes all notification targets.
|
||||
func (evnot *EventNotifier) RemoveAllRemoteTargets() {
|
||||
// RemoveAllBucketTargets - closes and removes all notification targets.
|
||||
func (evnot *EventNotifier) RemoveAllBucketTargets() {
|
||||
evnot.Lock()
|
||||
defer evnot.Unlock()
|
||||
|
||||
for _, targetMap := range evnot.bucketRemoteTargetRulesMap {
|
||||
targetIDSet := event.NewTargetIDSet()
|
||||
for k := range targetMap {
|
||||
targetIDSet[k] = struct{}{}
|
||||
}
|
||||
evnot.targetList.Remove(targetIDSet)
|
||||
targetIDSet := event.NewTargetIDSet()
|
||||
for k := range evnot.targetList.TargetMap() {
|
||||
targetIDSet[k] = struct{}{}
|
||||
}
|
||||
evnot.targetList.Remove(targetIDSet)
|
||||
}
|
||||
|
||||
// Send - sends the event to all registered notification targets
|
||||
@@ -209,7 +192,8 @@ func (evnot *EventNotifier) Send(args eventArgs) {
|
||||
return
|
||||
}
|
||||
|
||||
evnot.targetList.Send(args.ToEvent(true), targetIDSet, evnot.targetResCh)
|
||||
// If MINIO_API_SYNC_EVENTS is set, send events synchronously.
|
||||
evnot.targetList.Send(args.ToEvent(true), targetIDSet, evnot.targetResCh, globalAPIConfig.isSyncEventsEnabled())
|
||||
}
|
||||
|
||||
type eventArgs struct {
|
||||
|
||||
@@ -52,6 +52,7 @@ type apiConfig struct {
|
||||
disableODirect bool
|
||||
gzipObjects bool
|
||||
rootAccess bool
|
||||
syncEvents bool
|
||||
}
|
||||
|
||||
const cgroupLimitFile = "/sys/fs/cgroup/memory/memory.limit_in_bytes"
|
||||
@@ -166,6 +167,7 @@ func (t *apiConfig) init(cfg api.Config, setDriveCounts []int) {
|
||||
t.disableODirect = cfg.DisableODirect
|
||||
t.gzipObjects = cfg.GzipObjects
|
||||
t.rootAccess = cfg.RootAccess
|
||||
t.syncEvents = cfg.SyncEvents
|
||||
}
|
||||
|
||||
func (t *apiConfig) isDisableODirect() bool {
|
||||
@@ -353,3 +355,10 @@ func (t *apiConfig) getTransitionWorkers() int {
|
||||
|
||||
return t.transitionWorkers
|
||||
}
|
||||
|
||||
func (t *apiConfig) isSyncEventsEnabled() bool {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
|
||||
return t.syncEvents
|
||||
}
|
||||
|
||||
@@ -1032,7 +1032,6 @@ func (sys *NotificationSys) GetPeerOnlineCount() (nodesOnline, nodesOffline int)
|
||||
|
||||
// NewNotificationSys - creates new notification system object.
|
||||
func NewNotificationSys(endpoints EndpointServerPools) *NotificationSys {
|
||||
// targetList/bucketRulesMap/bucketRemoteTargetRulesMap are populated by NotificationSys.Init()
|
||||
remote, all := newPeerRestClients(endpoints)
|
||||
return &NotificationSys{
|
||||
peerClients: remote,
|
||||
|
||||
@@ -51,10 +51,6 @@ func handleSignals() {
|
||||
// send signal to various go-routines that they need to quit.
|
||||
cancelGlobalContext()
|
||||
|
||||
if globalEventNotifier != nil {
|
||||
globalEventNotifier.RemoveAllRemoteTargets()
|
||||
}
|
||||
|
||||
if httpServer := newHTTPServerFn(); httpServer != nil {
|
||||
err = httpServer.Shutdown()
|
||||
if !errors.Is(err, http.ErrServerClosed) {
|
||||
@@ -71,6 +67,10 @@ func handleSignals() {
|
||||
logger.LogIf(context.Background(), srv.Shutdown())
|
||||
}
|
||||
|
||||
if globalEventNotifier != nil {
|
||||
globalEventNotifier.RemoveAllBucketTargets()
|
||||
}
|
||||
|
||||
return (err == nil && oerr == nil)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user