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

Make Hue and Spotify setup tasks singletons #16

Merged
merged 6 commits into from
Jan 5, 2024
Merged

Conversation

BeeStag
Copy link
Collaborator

@BeeStag BeeStag commented Nov 2, 2023

UPDATE: the fix for issue 17 is actually changing this line to reference data.data.auth_url. But this PR is still useful.

The Spotify config is crashing because React is running in dev mode, so it's making its API calls twice on purpose to try to screw us up/reveal errors. This revealed that the Spotify setup task (and really, both setup tasks) needs to be idempotent/a singleton task/etc., because while the Hue task's lack of singleton-ness wasn't downright messing it up, the Spotify task couldn't have 2 threads listening on port 8888 at the same time.

changes:

  • add SingletonTask class (extends celery Task class) - right now its sole purpose is its run_singleton_task decorator (which could just be used as a standalone function, so the @task(base=SingletonTask) param is not necessary at this point for the code to work), but I like having it encapsulated in a class in case we want to extend this class' functionality to accommodate the run_spotihue task (right now SingletonTask does NOT accommodate the run_spotihue task).

  • add SingletonTaskLock class - keeps track of (task name, task ID) key-value pairs in Redis, with only 1 task ID allowed to "have" a singleton task's name (lock) at a time. its "acquire lock" logic is in a context manager that's used by the SingletonTask.run_singleton_task decorator. inspiration was: https://docs.celeryq.dev/en/latest/tutorials/task-cookbook.html#ensuring-a-task-is-only-executed-one-at-a-time

  • made the Hue and Spotify setup tasks "bound" tasks (meaning their 1st argument is their own self/instance - even though they don't use self, their decorator does).

  • make sure the Spotify setup's local socket only listens on 8888 for a couple minutes, so that it can go ahead and peacefully error out and let that Spotify setup task relinquish its lock so that a new Spotify setup task can try again.

oh and also,

  • move spotihue/requirements.txt to spotihue/backend/dev_requirements.txt

right now SingletonTask doesn't accommodate the run_spotihue task because of it being a continually running task with no approximate runtime that can be estimated (the redis lock needs a ttl because not having one will screw things up if the app gets a ctrl-C termination or crashes). I'll probably extend our SingletonTask class logic to add lock refresh-ability at some point, for now I'm pushing this up so that we can fix the Spotify config error.

@BeeStag BeeStag changed the title Make Hue and Spotify setup tasks singletons (fix Spotify config crashing) Make Hue and Spotify setup tasks singletons Nov 30, 2023
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the name change here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since it's been a while and I can't remember exactly where we left this - I have an upcoming MR that will add a docker compose entry for the frontend service, and I thought it best to put requirement specifications for the frontend and backend in their own respective directories, for the sake of organization. Since these 2 requirements.txt files are both strictly Python module requirements for the backend, I moved this one into the backend directory. But I changed its name so as not to interfere with the backend's dockerfile, and for clarity (since this just-moved file is for dev requirements, and not the bare-bones requirements that the backend's dockerfile cares about).


from spotipy import oauth2, util


logger = logging.getLogger(__name__)

SPOTIFY_OAUTH_TIMEOUT = 60 * 3 # 3 minutes
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we create a .env for this to make it configurable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good call! will do

"""
@wraps(bound_task_function)
def wrapper(*args, **kwargs):
me = args[0]
Copy link
Owner

@mgibbs1259 mgibbs1259 Nov 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment here explaining this line based on our convo?

@celery_app.task
def setup_hue(backoff_seconds: int = 5, retries: int = 5) -> None:
@celery_app.task(base=SingletonTask, bind=True)
@SingletonTask.run_singleton_task
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run_singleton_task is static method

@BeeStag BeeStag merged commit 5b2ef16 into main Jan 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants