Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No current context #128

Closed
kercos opened this issue Jun 29, 2019 · 6 comments · Fixed by #131
Closed

No current context #128

kercos opened this issue Jun 29, 2019 · 6 comments · Fixed by #131
Assignees
Labels
priority: p1 Important issue which blocks shipping the next release. Will be fixed prior to next release. 🚨 This issue needs some love. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@kercos
Copy link

kercos commented Jun 29, 2019

Hi,
I'm not sure if this is a bug but it's not clear to me how to properly handle client.context() when handling multiple threads.

Steps to reproduce

  1. See code below

Code example

from google.cloud import datastore
from google.cloud import ndb

client = ndb.Client()

class Test(ndb.Model):
    name = ndb.StringProperty()
  

def test(input_name):    
    print('Adding {}'.format(input_name))
    with client.context():
        t = Test(
            name=input_name,             
        )        
        t.put()        
    print('Added {}'.format(input_name))

if __name__ == "__main__":
    import threading
    threading.Thread(target=test, args=['John']).start()
    threading.Thread(target=test, args=['Bob']).start()

Stack trace

Adding John
Adding Bob
Added John
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "ndb_test.py", line 16, in test
    t.put()
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/_options.py", line 93, in wrapper
    return wrapped(*pass_args, _options=_options, **kwargs)
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/model.py", line 4758, in _put
    return self._put_async(_options=_options).result()
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/tasklets.py", line 190, in result
    self.check_success()
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/tasklets.py", line 134, in check_success
    self.wait()
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/tasklets.py", line 126, in wait
    _eventloop.run1()
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/_eventloop.py", line 411, in run1
    loop.run1()
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/_eventloop.py", line 344, in run1
    delay = self.run0()
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/_eventloop.py", line 333, in run0
    callback(rpc)
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/tasklets.py", line 323, in done_callback
    _eventloop.call_soon(self._advance_tasklet, yielded.result())
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/_eventloop.py", line 380, in call_soon
    loop = get_event_loop()
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/_eventloop.py", line 368, in get_event_loop
    context = context_module.get_context()
  File "/Users/fedja/Code/Bots/HistoricTrentoBotPy3/env/lib/python3.7/site-packages/google/cloud/ndb/context.py", line 65, in get_context
    raise exceptions.ContextError()
google.cloud.ndb.exceptions.ContextError: No current context. NDB calls must be made in context established by google.cloud.ndb.Client.context.
@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Jun 30, 2019
@chrisrossi chrisrossi self-assigned this Jun 30, 2019
@chrisrossi chrisrossi added 🚨 This issue needs some love. and removed triage me I really want to be triaged. labels Jun 30, 2019
@chrisrossi
Copy link
Contributor

I don't see anything obviously wrong in your example. I'm going to treat this as a bug and will investigate shortly. Thank you for reporting!

chrisrossi pushed a commit to chrisrossi/python-ndb that referenced this issue Jul 1, 2019
It turns out that if you use ``__slots__`` in a ``threading.local``
subclass, it no longer works as a ``threading.local`` instance. The more
you know...

Fixes googleapis#128.
@lchen4snap
Copy link

I'm using the cloud ndb in kubernetes. When I use put_async, I got context error:

google.cloud.ndb.exceptions.ContextError: No current context. NDB calls must be made in context established by google.cloud.ndb.Client.context.

Here's my test code:

    def create(self, key):
        report = ReportNDBTest(report_key=key)
        with self.client.context():
            report.put_async()

@chrisrossi
Copy link
Contributor

@lchen4snap I believe you've found bug #213. This is fixed, but the fix has not made its way to a release yet. For now you can use the master branch of this repo for all the most recent bug fixes. I'll ask about getting a release. Thanks!

@lchen4snap
Copy link

@lchen4snap I believe you've found bug #213. This is fixed, but the fix has not made its way to a release yet. For now you can use the master branch of this repo for all the most recent bug fixes. I'll ask about getting a release. Thanks!

Good to know. Thank you @chrisrossi !

@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Apr 6, 2020
@freelancing-solutions
Copy link

hasnt this issue been fixed yet

@freelancing-solutions
Copy link

Ok actually i found the solution its not a bug
you need to use context when you start a thread like this

      @app.after_request
      @use_context
      def start_thread(response: Response) -> Response:
          """
              **start thread**
                  starting a separate thread to deal with tasks that where put aside during the request
          """
          app.tasks_thread.start()
          return response

and use tasklets to save data inside the threads

    @tasklet
    def save_model(self, model: ndb.Model) -> Future:
        yield model.put_async()
   

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p1 Important issue which blocks shipping the next release. Will be fixed prior to next release. 🚨 This issue needs some love. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants