github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/pkg/realtime/realtime.go (about) 1 package realtime 2 3 import ( 4 "sync" 5 6 "github.com/cozy/cozy-stack/pkg/config/config" 7 "github.com/cozy/cozy-stack/pkg/prefixer" 8 ) 9 10 // Basic data events 11 const ( 12 EventCreate = "CREATED" 13 EventUpdate = "UPDATED" 14 EventDelete = "DELETED" 15 EventNotify = "NOTIFIED" 16 ) 17 18 // Doc is an interface for a object with DocType, ID 19 type Doc interface { 20 ID() string 21 DocType() string 22 } 23 24 // Event is the basic message structure manipulated by the realtime package 25 type Event struct { 26 Cluster int `json:"cluster,omitempty"` 27 Domain string `json:"domain"` 28 Prefix string `json:"prefix,omitempty"` 29 Verb string `json:"verb"` 30 Doc Doc `json:"doc"` 31 OldDoc Doc `json:"old,omitempty"` 32 } 33 34 func newEvent(db prefixer.Prefixer, verb string, doc Doc, oldDoc Doc) *Event { 35 return &Event{ 36 Cluster: db.DBCluster(), 37 Domain: db.DomainName(), 38 Prefix: db.DBPrefix(), 39 Verb: verb, 40 Doc: doc, 41 OldDoc: oldDoc, 42 } 43 } 44 45 // DBCluster implements the prefixer.Prefixer interface. 46 func (e *Event) DBCluster() int { 47 return e.Cluster 48 } 49 50 // DBPrefix implements the prefixer.Prefixer interface. 51 func (e *Event) DBPrefix() string { 52 if e.Prefix != "" { 53 return e.Prefix 54 } 55 return e.Domain 56 } 57 58 // DomainName implements the prefixer.Prefixer interface. 59 func (e *Event) DomainName() string { 60 return e.Domain 61 } 62 63 // The following API is inspired by https://github.com/gocontrib/pubsub 64 65 // Hub is an object which recive events and calls appropriate listener 66 type Hub interface { 67 // Emit is used by publishers when an event occurs 68 Publish(db prefixer.Prefixer, verb string, doc Doc, oldDoc Doc) 69 70 // Subscriber creates a Subscriber that can subscribe to several 71 // doctypes. Call its Close method to Unsubscribe. 72 Subscriber(prefixer.Prefixer) *Subscriber 73 74 // SubscribeFirehose adds a listener for all events that happened in this 75 // cozy-stack process. 76 SubscribeFirehose() *Subscriber 77 78 subscribe(sub *Subscriber, key string) 79 unsubscribe(sub *Subscriber, key string) 80 watch(sub *Subscriber, key, id string) 81 unwatch(sub *Subscriber, key, id string) 82 close(sub *Subscriber) 83 } 84 85 var globalHubMu sync.Mutex 86 var globalHub Hub 87 88 // GetHub returns the global hub 89 func GetHub() Hub { 90 globalHubMu.Lock() 91 defer globalHubMu.Unlock() 92 if globalHub != nil { 93 return globalHub 94 } 95 cli := config.GetConfig().Realtime 96 if cli == nil { 97 globalHub = newMemHub() 98 } else { 99 globalHub = newRedisHub(cli) 100 } 101 return globalHub 102 }