Skip to content

Frame retry default/max should be configurable without recompiling Cuebot #2477

Description

@DiegoTavares

Summary

There is no way to configure the default (or maximum) frame retry count for submitted jobs without editing Java source and recompiling Cuebot. The values are compile-time constants in JobSpec.java, and the current defaults silently clamp every job to 1 retry regardless of what the client requests. This should be configurable via opencue.properties (and/or the CONFIG DB table) so operators can set a facility-wide default without a custom build.

Current behavior

Retries at submission time are governed by two compile-time constants in cuebot/src/main/java/com/imageworks/spcue/service/JobSpec.java:

public static final int FRAME_RETRIES_DEFAULT = 1;  // applied only when the spec omits <maxretries>
public static final int FRAME_RETRIES_MAX = 1;      // hard cap — clamps whatever the client sends
public static final int FRAME_RETRIES_MIN = 0;

Parse path (JobSpec.java ~L301, L317-324):

job.maxRetries = FRAME_RETRIES_DEFAULT;
...
if (jobTag.getChildTextTrim("maxretries") != null) {
    job.maxRetries = Integer.valueOf(jobTag.getChildTextTrim("maxretries"));
    if (job.maxRetries > FRAME_RETRIES_MAX) {
        job.maxRetries = FRAME_RETRIES_MAX;   // clamps DOWN to 1
    } else if (job.maxRetries < FRAME_RETRIES_MIN) {
        job.maxRetries = FRAME_RETRIES_MIN;
    }
}

The clamp is the footgun: pyoutline always emits a <maxretries> tag (default 2 from pyoutline/outline/outline.cfg), so every normal job hits the > FRAME_RETRIES_MAX branch and is clamped to 1. This has been the case since the initial 2018 import (FRAME_RETRIES_MAX = 1 unchanged).

At runtime, FrameCompleteHandler marks a frame DEAD when frame.retries >= job.maxRetries, so the clamped value directly limits how many times a frame reruns before dying.

Things that look like config but aren't

  • job.int_max_retries SMALLINT DEFAULT 3 (V1__Initial_schema.sql) — never applies; the job INSERT always supplies job.maxRetries explicitly (JobDaoJdbc), overriding the column default.
  • CONFIG.MAX_FRAME_RETRIES = 16 (seed_data.sql) — only consulted by JobDaoJdbc.updateMaxFrameRetries(), i.e. the post-submission SetMaxRetries gRPC/API ceiling. It is not read during job submission.
  • No opencue.properties key exists for default/max frame retries. (dispatcher.frame_kill_retry_limit is unrelated — it governs kill-RPC retries.)

Why this is a problem

To make all jobs default to, say, 3 retries today, an operator must:

  1. Edit FRAME_RETRIES_DEFAULT = 3 and FRAME_RETRIES_MAX = 3 in JobSpec.java (editing only DEFAULT does nothing, because the client's <maxretries> tag gets clamped by MAX),
  2. Edit pyoutline/outline/outline.cfg maxretries = 3,
  3. Rebuild and redeploy a custom Cuebot image.

That's a source fork just to change a policy number, which is a poor operator experience for a Dockerized deployment.

Proposed solution

Make the default and max frame retries runtime-configurable, with the existing constants as fallback defaults. Preferred: opencue.properties (consistent with other dispatcher tunables), e.g.:

# Default frame retries applied when a job spec omits <maxretries>
dispatcher.frame_retries_default=1
# Upper bound clamp applied to job-spec <maxretries> at submission
dispatcher.frame_retries_max=16

Wire these into JobSpec (via injected config) so FRAME_RETRIES_DEFAULT / FRAME_RETRIES_MAX read the property with the current constant as the fallback default. Alternatively (or additionally), source the submission-time max from the existing CONFIG.MAX_FRAME_RETRIES row so there's a single DB-backed source of truth shared with the SetMaxRetries API.

Acceptance criteria

  • Operators can set a facility-wide default retry count via configuration only (no recompile).
  • The submission-time clamp is configurable and defaults to a sane value (>= the client default so pyoutline's maxretries isn't silently reduced).
  • Backward compatible: absent config, behavior matches today's constants.
  • Document the new keys in opencue.properties (relates to Documentation: many properties in cuebot/opencue.properties lack inline docs #2393).

Additional notes

  • Consider raising the stock FRAME_RETRIES_MAX default — clamping to 1 while pyoutline ships a default of 2 means the two defaults contradict each other out of the box.
  • There's also a hardcoded job.maxRetries = 2 in the PostJobs path (JobSpec.java ~L945) that should honor the same config.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions