Skip to content

feat: add clear expired tokens task in ol-social-auth#778

Merged
Anas12091101 merged 7 commits intomainfrom
anas/add-clear_expired_tokens-task
Apr 17, 2026
Merged

feat: add clear expired tokens task in ol-social-auth#778
Anas12091101 merged 7 commits intomainfrom
anas/add-clear_expired_tokens-task

Conversation

@Anas12091101
Copy link
Copy Markdown
Contributor

What are the relevant tickets?

https://github.com/mitodl/hq/issues/10116

Description (What does it do?)

This PR adds a clear_expired_tokens task in the ol-social-auth plugin to periodically delete the expired access and refresh tokens from the edX database.

Screenshots (if appropriate):

  • Desktop screenshots
  • Mobile width screenshots

How can this be tested?

  • Use this seed_tokens.py script to generate the seed data. This will create 500k expired access and refresh tokens.
  • In the LMS shell run the task:
     from ol_social_auth.tasks import clear_expired_tokens
     clear_expired_tokens.delay()
  • Verify that all the expired access and refresh tokens have been deleted successfully, and non-expired tokens are still present

Additional Context

Comment thread src/ol_social_auth/ol_social_auth/settings/common.py
@Anas12091101 Anas12091101 changed the title Anas/add clear expired tokens task feat: add clear expired tokens task in ol-social-auth Apr 1, 2026
@arslanashraf7 arslanashraf7 self-assigned this Apr 1, 2026
)
if not hasattr(settings, "CELERY_BEAT_SCHEDULE"):
settings.CELERY_BEAT_SCHEDULE = {}
settings.CELERY_BEAT_SCHEDULE["clear_expired_tokens"] = {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's distinguish it.

Suggested change
settings.CELERY_BEAT_SCHEDULE["clear_expired_tokens"] = {
settings.CELERY_BEAT_SCHEDULE["ol_clear_expired_tokens"] = {

if not hasattr(settings, "CELERY_BEAT_SCHEDULE"):
settings.CELERY_BEAT_SCHEDULE = {}
settings.CELERY_BEAT_SCHEDULE["clear_expired_tokens"] = {
"task": "ol_social_auth.tasks.clear_expired_tokens",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's do it here as well

Suggested change
"task": "ol_social_auth.tasks.clear_expired_tokens",
"task": "ol_social_auth.tasks.ol_clear_expired_tokens",

settings.CELERY_BEAT_SCHEDULE = {}
settings.CELERY_BEAT_SCHEDULE["clear_expired_tokens"] = {
"task": "ol_social_auth.tasks.clear_expired_tokens",
"schedule": crontab(hour=9, minute=0, day_of_week="monday"),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why not midnight?

Suggested change
"schedule": crontab(hour=9, minute=0, day_of_week="monday"),
"schedule": crontab(hour=0, minute=0, day_of_week="monday"),

Copy link
Copy Markdown
Contributor Author

@Anas12091101 Anas12091101 Apr 8, 2026

Choose a reason for hiding this comment

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

I’m not entirely sure, but this task is scheduled for 9 AM in our other applications as well; for example, MITxOnline and MITxPRO

@pdpinch, what are your thoughts on this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it's a task that we care about succeeding, I prefer to do it during business hours, so we have a better chance of noticing a problem and fixing it.

For this task, like this, really, any time would be fine.



def plugin_settings(settings):
"""Add clear_expired_tokens to the Celery beat schedule."""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The docstrings are for the while plugin_settings, so they need to be generic.

Comment on lines +16 to +18
# Suppress debug-level logs from oauth2_provider during cleanup.
# Its batch_delete debug logs lack the 'userid' field expected by
# Open edX's custom log formatter, causing noisy ValueError tracebacks.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you explain this a little bit more? I am having a hard time getting it. Did we copy it from Open edX?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This wasn't copied from Open edX — it's a workaround for an incompatibility between django-oauth-toolkit and Open edX's custom log formatter.

The problem: clear_expired() internally calls batch_delete(), which emits debug-level log messages like "10000 tokens deleted, X left". Open edX configures a custom log formatter that expects every log record to have a userid field (used for request-scoped user tracking). The oauth2_provider library doesn't add this field to its log records, so every debug message it emits causes a ValueError: Formatting field not found in record: 'userid' — producing a noisy traceback in the logs on every batch deletion.

The fix: Before calling clear_expired(), we temporarily raise the oauth2_provider logger level to INFO, which silences the debug-level batch messages. After the call completes (or fails), we restore the original level. This way the deletion still happens correctly — we just suppress the log messages that would trigger the formatter error.

To reproduce the issue, run the clear_expired() fn without suppressing the logs.

Comment thread src/ol_social_auth/README.rst Outdated

**Behavior:**

* Runs every **Monday at 9:00 AM** (server time) via Celery Beat by default. The schedule can be customized by overriding the ``clear_expired_tokens`` entry in ``CELERY_BEAT_SCHEDULE``.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this will change too if we decide to run the task at midnight.

Comment on lines +12 to +16
if not hasattr(settings, "CELERY_BEAT_SCHEDULE"):
settings.CELERY_BEAT_SCHEDULE = {}
settings.CELERY_BEAT_SCHEDULE["ol_clear_expired_tokens"] = {
"task": "ol_social_auth.tasks.ol_clear_expired_tokens",
"schedule": crontab(hour=9, minute=0, day_of_week="monday"),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was able to test it manually via Django shell, but I wasn't able to test it via the beat schedule and the task being run in auto mode. Were you able to test it?

Also, Open edX has CELERYBEAT_SCHEDULE in the settings in common.py instead of CELERY_BEAT_SCHEDULE. Could you tell if there was any specific reason for using a new env key rather than using the existing openedx one? And also, could this be the reason the task schedule isn't working?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch. I’ve updated the setting name in dce4d4b and verified that the tasks are running as expected according to the beat schedule.

Copy link
Copy Markdown
Contributor

@arslanashraf7 arslanashraf7 left a comment

Choose a reason for hiding this comment

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

LGTM 👍 One question for @blarghmatey before merging.

def plugin_settings(settings):
"""Settings for the ol-social-auth plugin.""" # noqa: D401
settings.OAUTH2_PROVIDER["REFRESH_TOKEN_EXPIRE_SECONDS"] = (
30 * 24 * 60 * 60 # 30 days
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd suggest checking with @blarghmatey this time range as well, since we're using service tokens before merging the PR. Since DevOps creates service tokens, I'm not sure what expiry time they set. I want to make sure they will not be deleted automatically.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The OAuth service accounts that we rely on are using client credentials grants so we're not worried about token expiration. Thanks for checking.

@Anas12091101 Anas12091101 merged commit fef5276 into main Apr 17, 2026
10 checks passed
@Anas12091101 Anas12091101 deleted the anas/add-clear_expired_tokens-task branch April 17, 2026 12:37
Copilot AI pushed a commit that referenced this pull request Apr 21, 2026
* feat: add task

* fix: issues

* chore: bump version

* docs: update readme

* fix: issues

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix: rename to CELERYBEAT_SCHEDULE

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: arslanashraf7 <34372316+arslanashraf7@users.noreply.github.com>
Copilot AI added a commit that referenced this pull request Apr 21, 2026
Reverts the changes introduced by two commits that were accidentally
included in this branch during an earlier rebase on a shallow clone:
- f71e486 (feat: add clear expired tokens task in ol-social-auth #778)
- 7226134 ([pre-commit.ci] pre-commit autoupdate #783)

These commits are already in main; including them here caused the PR
to show unrelated ol_social_auth and pre-commit changes.

Co-authored-by: arslanashraf7 <34372316+arslanashraf7@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants