Skip to content

v0.22.1#339

Merged
Archmonger merged 2 commits intomainfrom
v0.22.1
Mar 25, 2026
Merged

v0.22.1#339
Archmonger merged 2 commits intomainfrom
v0.22.1

Conversation

@Archmonger
Copy link
Copy Markdown
Owner

@Archmonger Archmonger commented Mar 25, 2026

Description

Modify background task manager to utilize filesystem rather than unstable sqlite implementation.

Checklist

Please update this checklist as you complete each item:

  • Tests have been developed for bug fixes or new functionality.
  • The changelog has been updated, if necessary.
  • Documentation has been updated, if necessary.
  • GitHub Issues closed by this PR have been linked.

By submitting this pull request I agree that all contributions comply with this project's open source license(s).

Summary by Sourcery

Switch background task management from a SQLite-backed Huey configuration to a filesystem-based Huey implementation with cross-platform file locking support.

Enhancements:

  • Replace the SQLite-based Huey configuration with a FileHuey setup that stores tasks on the filesystem.
  • Introduce a custom file lock implementation and monkey patch Huey on Windows to ensure cross-platform file locking.
  • Remove SQLite-specific background task maintenance and setup logic that is no longer needed for the task queue backend.
  • Clean up a stray debug log statement in the frontend click handler.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 25, 2026

Reviewer's Guide

Switches background task processing from a SQLite-backed Huey setup to a filesystem-based Huey configuration with a custom cross-platform file-lock implementation, and removes now-unused SQLite-related setup and maintenance code, along with a small client-side cleanup and version/requirements updates.

Sequence diagram for filesystem-based Huey background task processing

sequenceDiagram
    actor User
    participant WebApp
    participant HueyClient
    participant FileHuey
    participant FileLock
    participant TaskFiles

    User->>WebApp: Trigger_endpoint_requiring_background_work
    WebApp->>HueyClient: enqueue_task(args)
    HueyClient->>FileHuey: add_task(task_data)
    FileHuey->>FileLock: __enter__()
    activate FileLock
    FileLock-->>FileHuey: acquired_lock
    FileHuey->>TaskFiles: write_task_file()
    FileHuey->>FileLock: __exit__()
    deactivate FileLock

    Note over FileHuey,TaskFiles: Task is now persisted in filesystem-backed store

    participant HueyConsumer
    HueyConsumer->>FileHuey: poll_for_tasks()
    FileHuey->>FileLock: __enter__()
    activate FileLock
    FileLock-->>FileHuey: acquired_lock
    FileHuey->>TaskFiles: read_and_pop_next_task()
    FileHuey->>FileLock: __exit__()
    deactivate FileLock
    FileHuey-->>HueyConsumer: task_data
    HueyConsumer->>HueyConsumer: execute_task()
Loading

Class diagram for custom FileLock and Huey integration

classDiagram
    class FileLock {
        -filename : str
        -fd : int
        +FileLock(filename : str)
        +acquire() void
        +release() void
        +__enter__() FileLock
        +__exit__(exc_type, exc_val, exc_tb) void
    }

    class HueyUtils {
        <<module>>
        +FileLock
    }

    class SettingsHUEY {
        <<settings_dict>>
        +name : str
        +huey_class : str
        +path : str
        +immediate : bool
        +use_thread_lock : bool
        +consumer_workers : int
        +consumer_initial_delay : float
    }

    HueyUtils ..> FileLock : assigned_as_FileLock
    SettingsHUEY ..> FileLock : used_for_file_locking_on_win32
    SettingsHUEY ..> FileHuey : configures

    class FileHuey {
        <<Huey_backend>>
    }
Loading

File-Level Changes

Change Details Files
Introduce a custom cross-platform file-lock implementation and apply it to Huey on Windows.
  • Add an OS-agnostic FileLock class using os.open/os.close for locking and unlocking files.
  • Ensure the lock directory exists, deleting any pre-existing lock file before acquiring a new lock.
  • Monkey-patch huey.utils.FileLock with the custom implementation when running on win32 platforms.
conreq/__init__.py
Reconfigure Huey to use a filesystem-based task store instead of SQLite and simplify consumer settings.
  • Remove HUEY_FILENAME and SQLite-specific Huey settings including SqliteHuey class, filename, isolation/connection tuning, and worker health checks.
  • Configure HUEY to use huey.FileHuey with a filesystem path under DATA_DIR for task storage.
  • Enable thread-based locking for Huey via use_thread_lock and simplify consumer configuration (workers, initial_delay).
conreq/settings.py
Remove SQLite-backed Huey database maintenance and bootstrap logic now that Huey no longer uses its own SQLite DB.
  • Delete the periodic huey_db_maintenance task that pruned and optimized the Huey SQLite database.
  • Stop preconfig_conreq from setting up file permissions/ownership for a separate Huey SQLite database file.
  • Remove unused HUEY_FILENAME references from management commands that previously depended on the SQLite-based background task DB.
conreq/core/base/tasks.py
conreq/core/base/management/commands/preconfig_conreq.py
conreq/core/base/management/commands/run_conreq.py
Minor client and project housekeeping updates.
  • Remove an unnecessary console.log from the quick request click handler to reduce noise in browser dev tools.
  • Update the VERSION file to v0.22.1.
  • Adjust Python dependency requirements in requirements/main.txt to align with the new release and Huey configuration.
conreq/core/base/static/js/events_click.js
VERSION
requirements/main.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@Archmonger Archmonger marked this pull request as ready for review March 25, 2026 13:41
@Archmonger Archmonger merged commit 51bbed6 into main Mar 25, 2026
7 checks passed
@Archmonger Archmonger deleted the v0.22.1 branch March 25, 2026 13:41
Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • The custom FileLock implementation unlinks any existing lock file in init, which can break an active lock held by another process; consider moving any cleanup into acquire with proper checks so multiple processes cannot silently invalidate each other’s locks.
  • os.makedirs(dirname) without exist_ok=True combined with a separate os.path.exists check is racy under concurrent startup; it’s safer to call os.makedirs(dirname, exist_ok=True) and drop the explicit existence check.
  • In the HUEY settings, removing the explicit worker_type may change behavior depending on Huey defaults; if a specific concurrency model is required, keep worker_type set explicitly to avoid subtle runtime differences.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The custom FileLock implementation unlinks any existing lock file in __init__, which can break an active lock held by another process; consider moving any cleanup into acquire with proper checks so multiple processes cannot silently invalidate each other’s locks.
- os.makedirs(dirname) without exist_ok=True combined with a separate os.path.exists check is racy under concurrent startup; it’s safer to call os.makedirs(dirname, exist_ok=True) and drop the explicit existence check.
- In the HUEY settings, removing the explicit worker_type may change behavior depending on Huey defaults; if a specific concurrency model is required, keep worker_type set explicitly to avoid subtle runtime differences.

## Individual Comments

### Comment 1
<location path="conreq/__init__.py" line_range="19-21" />
<code_context>
+        elif os.path.exists(self.filename):
+            os.unlink(self.filename)
+
+    def acquire(self):
+        flags = os.O_CREAT | os.O_TRUNC | os.O_RDWR
+        self.fd = os.open(self.filename, flags)
+
+    def release(self):
</code_context>
<issue_to_address>
**issue (bug_risk):** Current FileLock.acquire implementation does not provide actual mutual exclusion across processes.

Because the file is opened with `os.O_CREAT | os.O_TRUNC | os.O_RDWR` only, multiple processes can open the same lock file at once, so this does not enforce mutual exclusion (especially on Windows, where several processes can think they hold the lock). Please use `os.O_EXCL` or a platform-specific locking primitive (`msvcrt.locking` on Windows, `fcntl` on POSIX, etc.) so acquisition fails or blocks when another process already holds the lock, matching Huey’s `FileLock` semantics.
</issue_to_address>

### Comment 2
<location path="conreq/__init__.py" line_range="13-16" />
<code_context>
+        self.filename = filename
+        self.fd = None
+
+        dirname = os.path.dirname(filename)
+        if not os.path.exists(dirname):
+            os.makedirs(dirname)
+        elif os.path.exists(self.filename):
+            os.unlink(self.filename)
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Unconditionally deleting an existing lock file in __init__ can interfere with other processes and may raise errors for empty dirnames.

Two issues here:

1) Deleting `self.filename` in `__init__` can remove an active lock held by another process and break locking semantics. A lock implementation should not unconditionally delete a potentially valid lock file without verifying ownership.

2) If `filename` has no directory (e.g. `"lockfile"`), `os.path.dirname(filename)` is `''`, so `os.makedirs(dirname)` will be called with an empty string and fail. Guard against this with something like `if dirname and not os.path.exists(dirname):` and reconsider whether the eager unlink is needed here at all.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +19 to +21
def acquire(self):
flags = os.O_CREAT | os.O_TRUNC | os.O_RDWR
self.fd = os.open(self.filename, flags)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Current FileLock.acquire implementation does not provide actual mutual exclusion across processes.

Because the file is opened with os.O_CREAT | os.O_TRUNC | os.O_RDWR only, multiple processes can open the same lock file at once, so this does not enforce mutual exclusion (especially on Windows, where several processes can think they hold the lock). Please use os.O_EXCL or a platform-specific locking primitive (msvcrt.locking on Windows, fcntl on POSIX, etc.) so acquisition fails or blocks when another process already holds the lock, matching Huey’s FileLock semantics.

Comment on lines +13 to +16
dirname = os.path.dirname(filename)
if not os.path.exists(dirname):
os.makedirs(dirname)
elif os.path.exists(self.filename):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Unconditionally deleting an existing lock file in init can interfere with other processes and may raise errors for empty dirnames.

Two issues here:

  1. Deleting self.filename in __init__ can remove an active lock held by another process and break locking semantics. A lock implementation should not unconditionally delete a potentially valid lock file without verifying ownership.

  2. If filename has no directory (e.g. "lockfile"), os.path.dirname(filename) is '', so os.makedirs(dirname) will be called with an empty string and fail. Guard against this with something like if dirname and not os.path.exists(dirname): and reconsider whether the eager unlink is needed here at all.

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.

1 participant