• 
      

    Load extensions in more efficient batches.

    Review Request #15429 — Created Oct. 26, 2026 and updated

    Information

    Djblets
    release-6.x

    Reviewers

    Historically, extensions have always been initialized one at a time.
    Each time an extension is enabled, a number of things have to be
    registered in Django, and some of this involves rebuilding some internal
    state, which is not especially cheap.

    This change helps to batch this work during load so that we cut back on
    how often we perform these operations. A batch is processed through 3
    steps:

    1. Start the initialization of each extension in the batch. This is all
      the work done before registering apps in the Django app registry.

    2. Register all apps across all extensions in the batch in one update.

    3. Finish initialization of all extensions in the batch.

    If there are any issues registering the list of apps, the extensions
    will be broken out of the batch and initialized one-by-one. This helps
    to isolate any broken extensions and allow the rest to initialize and
    register.

    The extension manager will batch lists of extensions together that have
    the same dependency/requirement fulfillment status. so all extensions
    that do not depend on another extension will be in one batch, followed
    by all extensions that depend on those extensions, and so on.

    As part of this, a bug with extension dependencies and initialization
    was fixed. If an extension cannot be initialized, then none of the
    extensions that depend on it (directly or indirectly) can either. All
    will have load errors stored, giving admins details on what went wrong.

    Note that the order of initialization within batching does mean that if
    extension A tries to reach into extension B during initialize(), it
    may no longer be able to do that without problems unless it lists B as a
    requirement. It couldn't safely do this before either, since extension
    order was never guaranteed or in any way stable. With the
    requirement-based batches, there's at least now a stable way of doing
    this if needed. In practice, I'm not aware of any extensions that do
    this.

    Unit tests pass.

    Smoke-tested with a bunch of extensions. Tried enabling and disabling,
    doing full reloads, scans. No problems.

    Summary ID
    Load extensions in more efficient batches.
    Historically, extensions have always been initialized one at a time. Each time an extension is enabled, a number of things have to be registered in Django, and some of this involves rebuilding some internal state, which is not especially cheap. This change helps to batch this work during load so that we cut back on how often we perform these operations. A batch is processed through 3 steps: 1. Start the initialization of each extension in the batch. This is all the work done before registering apps in the Django app registry. 2. Register all apps across all extensions in the batch in one update. 3. Finish initialization of all extensions in the batch. If there are any issues registering the list of apps, the extensions will be broken out of the batch and initialized one-by-one. This helps to isolate any broken extensions and allow the rest to initialize and register. The extension manager will batch lists of extensions together that have the same dependency/requirement fulfillment status. so all extensions that do *not* depend on another extension will be in one batch, followed by all extensions that depend on those extensions, and so on. As part of this, a bug with extension dependencies and initialization was fixed. If an extension cannot be initialized, then none of the extensions that depend on it (directly or indirectly) can either. All will have load errors stored, giving admins details on what went wrong. Note that the order of initialization within batching does mean that if extension A tries to reach into extension B during `initialize()`, it may no longer be able to do that without problems unless it lists B as a requirement. It couldn't safely do this before either, since extension order was never guaranteed or in any way stable. With the requirement-based batches, there's at least now a stable way of doing this if needed. In practice, I'm not aware of any extensions that do this.
    c9e3213b689be558ee8a4a02bb397a684dbba309
    Description From Last Updated

    This method doesn't disable anything, it just doesn't initialize and records a load error.

    david david

    typo: for for

    david david

    This should have a separate check for elif requirement_id not in self._extension_classes and report an error that the required extension …

    david david
    Checks run (2 succeeded)
    flake8 passed.
    JSHint passed.
    david
    1. 
        
    2. djblets/extensions/manager.py (Diff revision 1)
       
       
       
       
       
      Show all issues

      This method doesn't disable anything, it just doesn't initialize and records a load error.

    3. djblets/extensions/manager.py (Diff revision 1)
       
       
      Show all issues

      typo: for for

    4. djblets/extensions/manager.py (Diff revision 1)
       
       
       
       
       
       
      Show all issues

      This should have a separate check for elif requirement_id not in self._extension_classes and report an error that the required extension is not installed.

    5.