dmontagu / fastapi-utils

Reusable utilities for FastAPI
MIT License
1.89k stars 165 forks source link

[BUG] repeat_every runs 4x per minute when specified to repeat every 60sec #257

Open thomashrabe opened 2 years ago

thomashrabe commented 2 years ago

Describe the bug I'm using repeat_every as in

@app.on_event("startup")
@repeat_every(seconds=60)
def scrumbot_alert():
    """
    Sends alert
    """
    now_tz = datetime.datetime.utcnow().astimezone(pytz.timezone(timezone))
    logging.error(now_tz)
    alert()

But when I put a log to track when that function is run, I get 4 logs for every minute.

ERROR:root:2022-04-15 08:20:28.842180-07:00
ERROR:root:2022-04-15 08:20:30.325091-07:00
ERROR:root:2022-04-15 08:20:35.036041-07:00
ERROR:root:2022-04-15 08:20:35.333271-07:00
ERROR:root:2022-04-15 08:21:28.843411-07:00
ERROR:root:2022-04-15 08:21:30.326840-07:00
ERROR:root:2022-04-15 08:21:35.037719-07:00
ERROR:root:2022-04-15 08:21:35.334868-07:00
ERROR:root:2022-04-15 08:22:28.844427-07:00
ERROR:root:2022-04-15 08:22:30.333721-07:00
ERROR:root:2022-04-15 08:22:35.039823-07:00
ERROR:root:2022-04-15 08:22:35.337983-07:00

Expected behavior Should see only one log per minute

Environment: OS: Ubuntu 20.04 fastapi utils: 0.2.1 fastapi: 0.60.1 pydantic: 1.4 python: 3.8

LindezaGrey commented 2 years ago

Hi, i ran into the same problem. if you want it to run once, make sure that your uvicorn/gunicorn config allows only one worker or one thread. in my setup i have an extra docker container in which the repeated task runs.

thomashrabe commented 2 years ago

Thanks @LindezaGrey , so you say this is because I run 4 workers and should reduce uvicorn to run only one worker, right?

LindezaGrey commented 2 years ago

Exactly. Because each worker is running the repeated task.

thomashrabe commented 2 years ago

Thanks, for now I scaled this down to 1 worker. Do you know if one can specify that only worker 1 can run specific code in fastapi? I think this would be a better solution than having only 1 worker or run a full service for this...

LindezaGrey commented 2 years ago

How is your deployment setup? I User docker and run 2 Containers, one with many workers for the usual api Service and one Container for the repeated Tasks. If you just run it from python you could also launch your app twice and make sure your repeated task instance uses a different Port or is not exposed at all.