Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 45dbb9e

Browse files
bryanmaupcostell
authored andcommitted
Cleanup thread state in python-compat runtime. (runtime:python27, vm:true)
Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=118080230
1 parent ecc346e commit 45dbb9e

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

ndb/google_imports.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
All other NDB code should import its Google App Engine modules from
1919
this module. If necessary, add new imports here (in both places).
2020
"""
21+
# pylint: disable=unused-import, g-import-not-at-top
2122

2223
import os
2324
import sys
@@ -86,6 +87,10 @@ def set_appengine_imports():
8687
from google.appengine.ext.blobstore import blobstore as ext_blobstore
8788
from google.appengine.ext import db
8889
from google.appengine.ext import gql
90+
try:
91+
from google.appengine.ext.vmruntime import callback
92+
except ImportError:
93+
callback = None
8994
from google.appengine.runtime import apiproxy_errors
9095
from google.net.proto import ProtocolBuffer
9196
else:
@@ -107,6 +112,7 @@ def set_appengine_imports():
107112
from google3.apphosting.ext.blobstore import blobstore as ext_blobstore
108113
from google3.apphosting.ext import db
109114
from google3.apphosting.ext import gql
115+
from google3.apphosting.ext.vmruntime import callback
110116
from google3.apphosting.runtime import apiproxy_errors
111117
from google3.net.proto import ProtocolBuffer
112118
# Prospective search is optional.

ndb/tasklets.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def foo():
8080
import os
8181
import sys
8282
import types
83+
import weakref
8384

8485
from .google_imports import apiproxy_stub_map
8586
from .google_imports import apiproxy_rpc
@@ -88,6 +89,7 @@ def foo():
8889
from .google_imports import datastore_pbs
8990
from .google_imports import datastore_rpc
9091
from .google_imports import namespace_manager
92+
from .google_imports import callback as _request_callback
9193

9294
from . import eventloop
9395
from . import utils
@@ -102,6 +104,8 @@ def foo():
102104

103105
_logging_debug = utils.logging_debug
104106

107+
_CALLBACK_KEY = '__CALLBACK__'
108+
105109

106110
def _is_generator(obj):
107111
"""Helper to test for a generator object.
@@ -115,12 +119,22 @@ def _is_generator(obj):
115119
class _State(utils.threading_local):
116120
"""Hold thread-local state."""
117121

118-
current_context = None
119-
120122
def __init__(self):
121123
super(_State, self).__init__()
124+
self.current_context = None
125+
self.all_generators = weakref.WeakSet()
122126
self.all_pending = set()
123127

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+
124138
def add_pending(self, fut):
125139
_logging_debug('all_pending: add %s', fut)
126140
self.all_pending.add(fut)
@@ -132,9 +146,18 @@ def remove_pending(self, fut, status='success'):
132146
else:
133147
_logging_debug('all_pending: %s: not found %s', status, fut)
134148

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+
135158
def clear_all_pending(self):
136159
if self.all_pending:
137-
logging.info('all_pending: clear %s', self.all_pending)
160+
_logging_debug('all_pending: clear %s', self.all_pending)
138161
self.all_pending.clear()
139162
else:
140163
_logging_debug('all_pending: clear no-op')
@@ -149,6 +172,13 @@ def dump_all_pending(self, verbose=False):
149172
pending.append(line)
150173
return '\n'.join(pending)
151174

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+
152182

153183
_state = _State()
154184

@@ -1021,6 +1051,7 @@ def tasklet_wrapper(*args, **kwds):
10211051
if _is_generator(result):
10221052
ns = namespace_manager.get_namespace()
10231053
ds_conn = datastore._GetConnection()
1054+
_state.add_generator(result)
10241055
eventloop.queue_call(None, fut._help_tasklet_along, ns, ds_conn, result)
10251056
else:
10261057
fut.set_result(result)
@@ -1210,7 +1241,7 @@ def _make_cloud_datastore_context(app_id, external_app_ids=()):
12101241
def set_context(new_context):
12111242
# XXX Docstring
12121243
os.environ[_CONTEXT_KEY] = '1'
1213-
_state.current_context = new_context
1244+
_state.set_context(new_context)
12141245

12151246
class _ThrowingStub(object):
12161247
"""A Stub implementation which always throws a NotImplementedError."""

0 commit comments

Comments
 (0)