@@ -79,7 +79,7 @@ func (c *baseClient) connect(ctx context.Context) error {
7979 // TODO enhance the cloudevents SKD to avoid wrapping the error type to distinguish the net connection
8080 // errors
8181 if err != nil {
82- // failed to reconnect, try agin
82+ // failed to reconnect, try again
8383 runtime .HandleErrorWithContext (ctx , err , "the cloudevents client reconnect failed" )
8484 <- wait .RealTimer (DelayFn ()).C ()
8585 continue
@@ -89,14 +89,11 @@ func (c *baseClient) connect(ctx context.Context) error {
8989 metrics .IncreaseClientReconnectedCounter (c .clientID )
9090 c .setClientReady (true )
9191 c .sendReceiverSignal (restartReceiverSignal )
92- c .sendReconnectedSignal ()
9392 }
9493
9594 select {
9695 case <- ctx .Done ():
97- if c .receiverChan != nil {
98- close (c .receiverChan )
99- }
96+ c .closeChannels ()
10097 return
10198 case err , ok := <- c .transport .ErrorChan ():
10299 if ! ok {
@@ -164,22 +161,52 @@ func (c *baseClient) subscribe(ctx context.Context, receive receiveFn) {
164161 return
165162 }
166163
164+ // send subscription request before starting to receive events
165+ if err := c .transport .Subscribe (ctx ); err != nil {
166+ runtime .HandleErrorWithContext (ctx , err , "failed to subscribe" )
167+ return
168+ }
169+
167170 c .receiverChan = make (chan int )
168171
169172 // start a go routine to handle cloudevents subscription
170173 go func () {
171- receiverCtx , receiverCancel := context .WithCancel (context . TODO () )
174+ receiverCtx , receiverCancel := context .WithCancel (ctx )
172175 startReceiving := true
176+ subscribed := true
173177
174178 for {
179+ if ! subscribed {
180+ // resubscribe before restarting the receiver
181+ if err := c .transport .Subscribe (ctx ); err != nil {
182+ if ctx .Err () != nil {
183+ receiverCancel ()
184+ return
185+ }
186+
187+ runtime .HandleError (fmt .Errorf ("failed to resubscribe, %v" , err ))
188+ select {
189+ case <- ctx .Done ():
190+ receiverCancel ()
191+ return
192+ case <- wait .RealTimer (DelayFn ()).C ():
193+ }
194+ continue
195+ }
196+ subscribed = true
197+ // notify the client caller to resync the resources
198+ c .sendReconnectedSignal (ctx )
199+ }
200+
175201 if startReceiving {
176202 go func () {
177- if err := c .transport .Receive (receiverCtx , func (evt cloudevents.Event ) {
203+ if err := c .transport .Receive (receiverCtx , func (ctx context.Context , evt cloudevents.Event ) {
204+ logger := klog .FromContext (ctx )
178205 logger .V (2 ).Info ("Received event" , "event" , evt .Context )
179206 if logger .V (5 ).Enabled () {
180207 logger .V (5 ).Info ("Received event" , "event" , evt .String ())
181208 }
182- receive (receiverCtx , evt )
209+ receive (ctx , evt )
183210 }); err != nil {
184211 runtime .HandleError (fmt .Errorf ("failed to receive cloudevents, %v" , err ))
185212 }
@@ -191,7 +218,7 @@ func (c *baseClient) subscribe(ctx context.Context, receive receiveFn) {
191218 case <- ctx .Done ():
192219 receiverCancel ()
193220 return
194- case signal , ok := <- c .receiverChan :
221+ case signal , ok := <- c .getReceiverChan () :
195222 if ! ok {
196223 // receiver channel is closed, stop the receiver
197224 receiverCancel ()
@@ -202,8 +229,9 @@ func (c *baseClient) subscribe(ctx context.Context, receive receiveFn) {
202229 case restartReceiverSignal :
203230 logger .V (2 ).Info ("restart the cloudevents receiver" )
204231 // rebuild the receiver context and restart receiving
205- receiverCtx , receiverCancel = context .WithCancel (context . TODO () )
232+ receiverCtx , receiverCancel = context .WithCancel (ctx )
206233 startReceiving = true
234+ subscribed = false
207235 case stopReceiverSignal :
208236 logger .V (2 ).Info ("stop the cloudevents receiver" )
209237 receiverCancel ()
@@ -224,10 +252,32 @@ func (c *baseClient) sendReceiverSignal(signal int) {
224252 }
225253}
226254
227- func (c * baseClient ) sendReconnectedSignal () {
255+ func (c * baseClient ) closeChannels () {
256+ c .Lock ()
257+ defer c .Unlock ()
258+
259+ if c .receiverChan != nil {
260+ close (c .receiverChan )
261+ c .receiverChan = nil
262+ }
263+ if c .reconnectedChan != nil {
264+ close (c .reconnectedChan )
265+ c .reconnectedChan = nil
266+ }
267+ }
268+
269+ func (c * baseClient ) sendReconnectedSignal (ctx context.Context ) {
228270 c .RLock ()
229271 defer c .RUnlock ()
230- c .reconnectedChan <- struct {}{}
272+ if c .reconnectedChan != nil {
273+ select {
274+ case c .reconnectedChan <- struct {}{}:
275+ // Signal sent successfully
276+ default :
277+ // No receiver listening on reconnectedChan, that's okay - don't block
278+ klog .FromContext (ctx ).Info ("reconnected signal not sent, no receiver listening" )
279+ }
280+ }
231281}
232282
233283func (c * baseClient ) isClientReady () bool {
@@ -241,3 +291,9 @@ func (c *baseClient) setClientReady(ready bool) {
241291 defer c .Unlock ()
242292 c .clientReady = ready
243293}
294+
295+ func (c * baseClient ) getReceiverChan () chan int {
296+ c .RLock ()
297+ defer c .RUnlock ()
298+ return c .receiverChan
299+ }
0 commit comments