@@ -80,6 +80,7 @@ def foo():
80
80
import os
81
81
import sys
82
82
import types
83
+ import weakref
83
84
84
85
from .google_imports import apiproxy_stub_map
85
86
from .google_imports import apiproxy_rpc
@@ -88,6 +89,7 @@ def foo():
88
89
from .google_imports import datastore_pbs
89
90
from .google_imports import datastore_rpc
90
91
from .google_imports import namespace_manager
92
+ from .google_imports import callback as _request_callback
91
93
92
94
from . import eventloop
93
95
from . import utils
@@ -102,6 +104,8 @@ def foo():
102
104
103
105
_logging_debug = utils .logging_debug
104
106
107
+ _CALLBACK_KEY = '__CALLBACK__'
108
+
105
109
106
110
def _is_generator (obj ):
107
111
"""Helper to test for a generator object.
@@ -115,12 +119,22 @@ def _is_generator(obj):
115
119
class _State (utils .threading_local ):
116
120
"""Hold thread-local state."""
117
121
118
- current_context = None
119
-
120
122
def __init__ (self ):
121
123
super (_State , self ).__init__ ()
124
+ self .current_context = None
125
+ self .all_generators = weakref .WeakSet ()
122
126
self .all_pending = set ()
123
127
128
+ def set_context (self , ctx ):
129
+ if _request_callback and _CALLBACK_KEY not in os .environ :
130
+ _request_callback .SetRequestEndCallback (self .reset )
131
+ os .environ [_CALLBACK_KEY ] = '1'
132
+ self .current_context = ctx
133
+
134
+ def add_generator (self , gen ):
135
+ _logging_debug ('all_generators: add %s' , gen )
136
+ self .all_generators .add (gen )
137
+
124
138
def add_pending (self , fut ):
125
139
_logging_debug ('all_pending: add %s' , fut )
126
140
self .all_pending .add (fut )
@@ -132,9 +146,18 @@ def remove_pending(self, fut, status='success'):
132
146
else :
133
147
_logging_debug ('all_pending: %s: not found %s' , status , fut )
134
148
149
+ def clear_all_generators (self ):
150
+ if self .all_generators :
151
+ _logging_debug ('all_generators: clear %s' , self .all_generators )
152
+ for gen in self .all_generators :
153
+ gen .close ()
154
+ self .all_generators .clear ()
155
+ else :
156
+ _logging_debug ('all_generators: clear no-op' )
157
+
135
158
def clear_all_pending (self ):
136
159
if self .all_pending :
137
- logging . info ('all_pending: clear %s' , self .all_pending )
160
+ _logging_debug ('all_pending: clear %s' , self .all_pending )
138
161
self .all_pending .clear ()
139
162
else :
140
163
_logging_debug ('all_pending: clear no-op' )
@@ -149,6 +172,13 @@ def dump_all_pending(self, verbose=False):
149
172
pending .append (line )
150
173
return '\n ' .join (pending )
151
174
175
+ def reset (self ):
176
+ self .current_context = None
177
+ ev = eventloop .get_event_loop ()
178
+ ev .clear ()
179
+ self .clear_all_pending ()
180
+ self .clear_all_generators ()
181
+
152
182
153
183
_state = _State ()
154
184
@@ -1021,6 +1051,7 @@ def tasklet_wrapper(*args, **kwds):
1021
1051
if _is_generator (result ):
1022
1052
ns = namespace_manager .get_namespace ()
1023
1053
ds_conn = datastore ._GetConnection ()
1054
+ _state .add_generator (result )
1024
1055
eventloop .queue_call (None , fut ._help_tasklet_along , ns , ds_conn , result )
1025
1056
else :
1026
1057
fut .set_result (result )
@@ -1210,7 +1241,7 @@ def _make_cloud_datastore_context(app_id, external_app_ids=()):
1210
1241
def set_context (new_context ):
1211
1242
# XXX Docstring
1212
1243
os .environ [_CONTEXT_KEY ] = '1'
1213
- _state .current_context = new_context
1244
+ _state .set_context ( new_context )
1214
1245
1215
1246
class _ThrowingStub (object ):
1216
1247
"""A Stub implementation which always throws a NotImplementedError."""
0 commit comments