Git Product home page Git Product logo

Comments (8)

bblommers avatar bblommers commented on June 11, 2024 1

Happy to help @nykolaslima!

There is a note in the FAQ that multi-threading in general is not supported. I'll see if I can extend that with this use case as an example.

I'll close this then, but let us know if you run into any other issues.

from moto.

bblommers avatar bblommers commented on June 11, 2024

Hi @nykolaslima, both UserPools and Users are stored in the global scope. So i don't quite understand what is going wrong in your example.

Are you able to provide a full reproducible test, in a standalone repo for example?

from moto.

nykolaslima avatar nykolaslima commented on June 11, 2024

Hi @bblommers , thanks for helping.

I found the problem. I am using pytest flask in order to start the flask app that is going to be tested. So I have two fixtures, one fixture to create the user in the cognito pool and other fixture to create the flask app.

@fixture
def logged_user(self, cognito_client, cognito_util, logged_user_password):
  user = UserTableFactory.create().to_domain()
  cognito_util.create_confirmed_user(user.email, logged_user_password)
  return user

@fixture
def app(self, cognito_client):
  os.environ['no_proxy'] = '*'
  app = create_app()
  app.config['SERVER_NAME'] = 'localhost'
  return app

With this code I do not guarantee that the logged_user will run before the app fixture. And what was happening is that the app was created first, and then the logged_user is created.
Looks like somehow the state that is used by the flask app is "copied" when the app is created, as the moto objects were used by value and not by reference - and in the moment that the app was created there were not users in the cognito pool.

to solve this, add the logged_user fixture as a dependency of app fixture we guarantee that the user will be created in the pool before the flask app - and then it works.

working code:

@fixture
def logged_user(self, cognito_client, cognito_util, logged_user_password):
  user = UserTableFactory.create().to_domain()
  cognito_util.create_confirmed_user(user.email, logged_user_password)
  return user

@fixture
def app(self, logged_user):
  os.environ['no_proxy'] = '*'
  app = create_app()
  app.config['SERVER_NAME'] = 'localhost'
  return app

Anyways it looks like a strange behavior since we supposed to share the same object, and if we are changing the users list inside of it, it should reflect in the flask app in the runtime, doesn't it?

from moto.

bblommers avatar bblommers commented on June 11, 2024

Looks like somehow the state that is used by the flask app is "copied" when the app is created

Based on that description, I think it is a multi-threading problem actually.
If you start a new thread, Python will copy everything in the global context to the new thread - which includes the UserPool (and now User).

Any future actions in a thread will only impact the state/global context in that thread, and resources created/updated by Flask (in the Flask-thread) will not show up in the main thread. So this setup really only works for read-only tests.

You might want to have a look at the Moto server. If all threads send their boto3-calls to a shared server, they're guaranteed to share state.

https://docs.getmoto.org/en/latest/docs/server_mode.html

from moto.

nykolaslima avatar nykolaslima commented on June 11, 2024

makes totally sense, thanks very much for the explanation.

actually in my context it would be ok to keep the read-only approach since I am creating the setup and doing some "black box" testing that doesn't really dig into the details of the mutate state.

I believe we can close the issue since it's not a bug but a multi thread behavior.

Do you believe it worth to mention about it somewhere in the docs?

from moto.

nykolaslima avatar nykolaslima commented on June 11, 2024

may I open a PR with this improvement?

I could create it if you help me to figure out where is the best place to put it.

from moto.

bblommers avatar bblommers commented on June 11, 2024

Sounds good to me!

I was planning on extending the second question here:
https://github.com/getmoto/moto/blob/master/docs%2Fdocs%2Ffaq.rst

Which would show up here:
https://docs.getmoto.org/en/latest/docs/faq.html

from moto.

nykolaslima avatar nykolaslima commented on June 11, 2024

Awesome. will work on some draft here and send you a PR

from moto.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.