@@ -21,72 +21,77 @@ import (
21
21
log "github.com/sirupsen/logrus"
22
22
)
23
23
24
+ type WebhookBroker struct {
25
+ // key is the hash of topic full name and pulsar url, and subscription name
26
+ webhooks map [string ]chan * SubCloseSignal
27
+ dbHandler db.Db
28
+ l * log.Entry
29
+ sync.RWMutex
30
+ }
31
+
24
32
// SubCloseSignal is a signal object to pass for channel
25
33
type SubCloseSignal struct {}
26
34
27
- // key is the hash of topic full name and pulsar url, and subscription name
28
- var webhooks = make (map [string ]chan * SubCloseSignal )
29
- var whLock = sync.RWMutex {}
35
+ func NewWebhookBroker (config * util.Configuration ) * WebhookBroker {
36
+ return & WebhookBroker {
37
+ dbHandler : db .NewDbWithPanic (config .PbDbType ),
38
+ webhooks : make (map [string ]chan * SubCloseSignal ),
39
+ l : log .WithFields (log.Fields {"app" : "webhookbroker" }),
40
+ }
41
+ }
30
42
31
43
// ReadWebhook reads a thread safe map
32
- func ReadWebhook (key string ) (chan * SubCloseSignal , bool ) {
33
- whLock .RLock ()
34
- defer whLock .RUnlock ()
35
- c , ok := webhooks [key ]
44
+ func ( wb * WebhookBroker ) ReadWebhook (key string ) (chan * SubCloseSignal , bool ) {
45
+ wb .RLock ()
46
+ defer wb .RUnlock ()
47
+ c , ok := wb . webhooks [key ]
36
48
return c , ok
37
49
}
38
50
39
51
// WriteWebhook writes a key/value to a thread safe map
40
- func WriteWebhook (key string , c chan * SubCloseSignal ) {
41
- whLock .Lock ()
42
- defer whLock .Unlock ()
43
- webhooks [key ] = c
52
+ func ( wb * WebhookBroker ) WriteWebhook (key string , c chan * SubCloseSignal ) {
53
+ wb .Lock ()
54
+ defer wb .Unlock ()
55
+ wb . webhooks [key ] = c
44
56
}
45
57
46
58
// DeleteWebhook deletes a key from a thread safe map
47
- func DeleteWebhook (key string ) bool {
48
- whLock .Lock ()
49
- defer whLock .Unlock ()
50
- if c , ok := webhooks [key ]; ok {
59
+ func ( wb * WebhookBroker ) DeleteWebhook (key string ) bool {
60
+ wb .Lock ()
61
+ defer wb .Unlock ()
62
+ if c , ok := wb . webhooks [key ]; ok {
51
63
c <- & SubCloseSignal {}
52
- delete (webhooks , key )
64
+ delete (wb . webhooks , key )
53
65
//channel is deleted where it's been created with `defer`
54
66
return ok
55
67
}
56
68
return false
57
69
}
58
70
59
- var singleDb db.Db
60
-
61
71
// Init initializes webhook configuration database
62
- func Init () {
63
- NewDbHandler ( )
64
- durationStr := util .AssignString (util . GetConfig () .PbDbInterval , "180s" )
72
+ func Init (config * util. Configuration ) {
73
+ svr := NewWebhookBroker ( config )
74
+ durationStr := util .AssignString (config .PbDbInterval , "180s" )
65
75
duration , err := time .ParseDuration (durationStr )
66
76
if err != nil {
67
- log .Errorf ("specified duration %s error %v" , durationStr , err )
77
+ svr . l .Errorf ("specified duration %s error %v" , durationStr , err )
68
78
duration , _ = time .ParseDuration ("180s" )
69
79
}
70
- log . Warnf ("beam database pull every %.0f seconds" , duration .Seconds ())
80
+ svr . l . Infof ("beam database pull every %.0f seconds" , duration .Seconds ())
71
81
72
82
go func () {
73
- run ()
83
+ svr . run ()
74
84
ticker := time .NewTicker (duration )
85
+ defer ticker .Stop ()
75
86
for {
76
87
select {
77
88
case <- ticker .C :
78
- run ()
89
+ svr . run ()
79
90
}
80
91
}
81
92
}()
82
93
}
83
94
84
- // NewDbHandler gets a local copy of Db handler
85
- func NewDbHandler () {
86
- log .Infof ("webhook database init..." )
87
- singleDb = db .NewDbWithPanic (util .GetConfig ().PbDbType )
88
- }
89
-
90
95
// pushWebhook sends data to a webhook interface
91
96
func pushWebhook (url string , data []byte , headers []string ) (int , * http.Response ) {
92
97
@@ -163,7 +168,7 @@ func pushAndAck(c pulsar.Consumer, msg pulsar.Message, url string, data []byte,
163
168
164
169
// ConsumeLoop consumes data from Pulsar topic
165
170
// Do not use context since go vet will puke that requires cancel invoked in the same function
166
- func ConsumeLoop (url , token , topic , subscriptionKey string , whCfg model.WebhookConfig ) error {
171
+ func ( wb * WebhookBroker ) ConsumeLoop (url , token , topic , subscriptionKey string , whCfg model.WebhookConfig ) error {
167
172
headers := whCfg .Headers
168
173
_ , err := model .GetSubscriptionType (whCfg .SubscriptionType )
169
174
if err != nil {
@@ -175,11 +180,11 @@ func ConsumeLoop(url, token, topic, subscriptionKey string, whCfg model.WebhookC
175
180
}
176
181
c , err := pulsardriver .GetPulsarConsumer (url , token , topic , whCfg .Subscription , whCfg .InitialPosition , whCfg .SubscriptionType , subscriptionKey )
177
182
if err != nil {
178
- return fmt .Errorf ("Failed to create Pulsar subscription %v" , err )
183
+ return fmt .Errorf ("failed to create Pulsar subscription %v" , err )
179
184
}
180
185
181
186
terminate := make (chan * SubCloseSignal , 2 )
182
- WriteWebhook (subscriptionKey , terminate )
187
+ wb . WriteWebhook (subscriptionKey , terminate )
183
188
defer close (terminate )
184
189
ctx := context .Background ()
185
190
@@ -189,18 +194,18 @@ func ConsumeLoop(url, token, topic, subscriptionKey string, whCfg model.WebhookC
189
194
retryMax := 3
190
195
for {
191
196
if retry > retryMax {
192
- cancelConsumer (subscriptionKey )
197
+ wb . cancelConsumer (subscriptionKey )
193
198
return fmt .Errorf ("consumer retried %d times, max reached" , retryMax )
194
199
}
195
200
msg , err := c .Receive (ctx )
196
201
if err != nil {
197
- log .Infof ("error from consumer loop receive: %v\n " , err )
202
+ wb . l .Infof ("error from consumer loop receive: %v\n " , err )
198
203
retry ++
199
204
ticker := time .NewTicker (time .Duration (2 * retry ) * time .Second )
200
205
defer ticker .Stop ()
201
206
select {
202
207
case <- terminate :
203
- log .Infof ("subscription %s received signal to exit consumer loop" , subscriptionKey )
208
+ wb . l .Infof ("subscription %s received signal to exit consumer loop" , subscriptionKey )
204
209
return nil
205
210
case <- ticker .C :
206
211
//reconnect after error
@@ -211,8 +216,8 @@ func ConsumeLoop(url, token, topic, subscriptionKey string, whCfg model.WebhookC
211
216
}
212
217
} else if msg != nil {
213
218
retry = 0
214
- if log . GetLevel () == log .DebugLevel {
215
- log . Debugf ("PulsarMessageId:%# v" , msg .ID ())
219
+ if wb . l . Level == log .DebugLevel {
220
+ wb . l . Debugf ("PulsarMessageId:%v" , msg .ID ())
216
221
}
217
222
headers = append (headers , fmt .Sprintf ("PulsarMessageId:%#v" , msg .ID ()))
218
223
headers = append (headers , "PulsarPublishedTime:" + msg .PublishTime ().String ())
@@ -229,61 +234,58 @@ func ConsumeLoop(url, token, topic, subscriptionKey string, whCfg model.WebhookC
229
234
if json .Valid (data ) {
230
235
headers = append (headers , "content-type:application/json" )
231
236
}
232
- if log .GetLevel () == log .DebugLevel {
233
- log .Debug (string (data ))
234
- }
235
237
pushAndAck (c , msg , whCfg .URL , data , headers )
236
238
}
237
239
}
238
240
239
241
}
240
242
241
- func run () {
243
+ func ( wb * WebhookBroker ) run () {
242
244
// key is hash of topic name and pulsar url, and subscription name
243
245
subscriptionSet := make (map [string ]bool )
244
246
245
- for _ , cfg := range LoadConfig () {
247
+ for _ , cfg := range wb . LoadConfig () {
246
248
for _ , whCfg := range cfg .Webhooks {
247
249
topic := cfg .TopicFullName
248
250
token := cfg .Token
249
251
url := cfg .PulsarURL
250
252
subscriptionKey := cfg .Key + whCfg .URL
251
253
status := whCfg .WebhookStatus
252
- _ , ok := ReadWebhook (subscriptionKey )
254
+ _ , ok := wb . ReadWebhook (subscriptionKey )
253
255
if status == model .Activated {
254
256
subscriptionSet [subscriptionKey ] = true
255
257
if ! ok {
256
- log .Infof ("start activated webhook for topic subscription %v" , subscriptionKey )
257
- go ConsumeLoop (url , token , topic , subscriptionKey , whCfg )
258
+ wb . l .Infof ("start activated webhook for topic subscription %v" , subscriptionKey )
259
+ go wb . ConsumeLoop (url , token , topic , subscriptionKey , whCfg )
258
260
}
259
261
}
260
262
}
261
263
}
262
264
263
265
// cancel any webhook which is no longer required to be activated by the database
264
- for k := range webhooks {
265
- if subscriptionSet [k ] != true {
266
- log .Infof ("cancel webhook consumer subscription key %s" , k )
267
- cancelConsumer (k )
266
+ for k := range wb . webhooks {
267
+ if ! subscriptionSet [k ] {
268
+ wb . l .Infof ("cancel webhook consumer subscription key %s" , k )
269
+ wb . cancelConsumer (k )
268
270
}
269
271
}
270
- log . Infof ("load webhooks size %d" , len (webhooks ))
272
+ wb . l . Infof ("load webhooks size %d" , len (wb . webhooks ))
271
273
}
272
274
273
275
// LoadConfig loads the entire topic documents from the database
274
- func LoadConfig () []* model.TopicConfig {
275
- cfgs , err := singleDb .Load ()
276
+ func ( wb * WebhookBroker ) LoadConfig () []* model.TopicConfig {
277
+ cfgs , err := wb . dbHandler .Load ()
276
278
if err != nil {
277
- log .Errorf ("failed to load topics from database error %v" , err .Error ())
279
+ wb . l .Errorf ("failed to load topics from database error %v" , err .Error ())
278
280
}
279
281
280
282
return cfgs
281
283
}
282
284
283
- func cancelConsumer (key string ) error {
284
- ok := DeleteWebhook (key )
285
+ func ( wb * WebhookBroker ) cancelConsumer (key string ) error {
286
+ ok := wb . DeleteWebhook (key )
285
287
if ok {
286
- log .Infof ("cancel consumer %v" , key )
288
+ wb . l .Infof ("cancel consumer %v" , key )
287
289
pulsardriver .CancelPulsarConsumer (key )
288
290
return nil
289
291
}
0 commit comments