1+ import logging
12import queue
23import threading
34from typing import Optional
1314)
1415from dapr .proto import api_v1 , appcallback_v1
1516
17+ logger = logging .getLogger (__name__ )
18+
1619
1720class Subscription :
1821 def __init__ (self , stub , pubsub_name , topic , metadata = None , dead_letter_topic = None ):
@@ -67,7 +70,7 @@ def outgoing_request_iterator():
6770 def reconnect_stream (self ):
6871 self .close ()
6972 DaprHealth .wait_for_sidecar ()
70- print ( 'Attempting to reconnect ...' )
73+ logger . info ( 'Subscription stream reconnecting ...' )
7174 self .start ()
7275
7376 def next_message (self ):
@@ -84,10 +87,17 @@ def next_message(self):
8487 message = next (self ._stream )
8588 return SubscriptionMessage (message .event_message )
8689 except RpcError as e :
87- # If Dapr can't be reached, wait until it's ready and reconnect the stream
88- if e .code () == StatusCode .UNAVAILABLE or e .code () == StatusCode .UNKNOWN :
89- print (
90- f'gRPC error while reading from stream: { e .details ()} , Status Code: { e .code ()} '
90+ # If Dapr can't be reached, wait until it's ready and reconnect the stream.
91+ # INTERNAL covers RST_STREAM from cloud proxies (e.g. Diagrid Cloud).
92+ if e .code () in (
93+ StatusCode .UNAVAILABLE ,
94+ StatusCode .UNKNOWN ,
95+ StatusCode .INTERNAL ,
96+ ):
97+ logger .warning (
98+ 'Subscription stream error (%s): %s — reconnecting' ,
99+ e .code (),
100+ e .details (),
91101 )
92102 self .reconnect_stream ()
93103 elif e .code () == StatusCode .CANCELLED :
@@ -111,7 +121,7 @@ def respond(self, message, status):
111121 raise StreamInactiveError ('Stream is not active' )
112122 self ._send_queue .put (msg )
113123 except Exception as e :
114- print (f"Can't send message on inactive stream: { e } " )
124+ logger . warning (f"Can't send message on inactive stream: { e } " )
115125
116126 def respond_success (self , message ):
117127 self .respond (message , TopicEventResponse ('success' ).status )
@@ -135,15 +145,12 @@ def _is_stream_active(self):
135145 return self ._stream_active
136146
137147 def close (self ):
148+ self ._set_stream_inactive ()
138149 if self ._stream :
139150 try :
140151 self ._stream .cancel ()
141- self ._set_stream_inactive ()
142- except RpcError as e :
143- if e .code () != StatusCode .CANCELLED :
144- raise Exception (f'Error while closing stream: { e } ' )
145- except Exception as e :
146- raise Exception (f'Error while closing stream: { e } ' )
152+ except Exception :
153+ pass # Stream already dead — safe to ignore
147154
148155 def __iter__ (self ):
149156 return self
0 commit comments