Skip to content

Lock expiration with per-script override - #308

Merged
krystian-panek-vmltech merged 15 commits into
mainfrom
lock-expiration-auto-recovery
Jul 28, 2026
Merged

Lock expiration with per-script override#308
krystian-panek-vmltech merged 15 commits into
mainfrom
lock-expiration-auto-recovery

Conversation

@krystian-panek-vmltech

Copy link
Copy Markdown
Collaborator

No description provided.

Copilot AI left a comment

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.

Pull request overview

This PR introduces expiring execution locks (with configurable TTL and per-script override) and adds a new LOCKED execution status, surfacing lock contention/stale-lock situations across the backend, UI, and documentation.

Changes:

  • Add LOCKED execution status and propagate it through queueing/execution logic and frontend rendering.
  • Implement lock TTL/expiration in the repository locker, plus a new “Lock Timeout” OSGi configuration and per-execution overrides.
  • Document lock timeout semantics and add UI help text/toasts and history filtering for locked executions.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
ui.frontend/src/types/execution.ts Adds LOCKED to the frontend execution status enum.
ui.frontend/src/pages/HistoryPage.tsx Adds “Locked” status filter item with icon in History.
ui.frontend/src/hooks/execution.ts Adds a toast message for LOCKED terminal status.
ui.frontend/src/components/ScriptsAutomaticHelpButton.tsx Documents lock behavior and expiration in the UI help dialog.
ui.frontend/src/components/ExecutionStatusBadge.tsx Adds LOCKED icon + badge variant handling.
ui.frontend/src/components/ExecutionProgressBar.tsx Treats LOCKED as a warning variant for completed display.
README.md Adds end-user documentation for lock timeout configuration and overrides.
core/src/main/java/dev/vml/es/acm/core/util/DurationUtils.java Introduces duration parsing utility for TTL inputs.
core/src/main/java/dev/vml/es/acm/core/repo/LockInfo.java Adds a value object for lock timestamps.
core/src/main/java/dev/vml/es/acm/core/repo/Locker.java Adds TTL support and lock expiration checks.
core/src/main/java/dev/vml/es/acm/core/code/Executor.java Uses expiring locks, logs lock info, and returns LOCKED when blocked.
core/src/main/java/dev/vml/es/acm/core/code/ExecutionStatus.java Adds backend LOCKED execution status.
core/src/main/java/dev/vml/es/acm/core/code/ExecutionQueue.java Propagates LOCKED back to the job result message and cancellation behavior.
core/src/main/java/dev/vml/es/acm/core/code/ExecutionContext.java Adds lockTimeout to the execution context for script/extension overrides.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core/src/main/java/dev/vml/es/acm/core/code/ExecutionContext.java Outdated
Comment thread core/src/main/java/dev/vml/es/acm/core/repo/Locker.java Outdated
Comment thread ui.frontend/src/hooks/execution.ts Outdated
@krystian-panek-vmltech krystian-panek-vmltech changed the title Lock expiration Lock expiration with per-script override Jul 27, 2026
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment thread core/src/main/java/dev/vml/es/acm/core/repo/Locker.java Outdated

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

core/src/main/java/dev/vml/es/acm/core/code/Executor.java:114

  • The new OSGi config description says only a negative value disables lock expiration, but the implementation treats any non-positive TTL as “no expiration” (ttl.isNegative() || ttl.isZero() in Locker.lock(...)), and the README also documents 0 as disabling expiration. Update the description to avoid confusing operators who set the value to 0.
        @AttributeDefinition(
                name = "Lock Timeout",
                description =
                        "Expiration time (in milliseconds) of executable locks, protecting against stale locks left behind when an instance is killed abruptly (e.g. pod recycling). Must exceed the max expected execution time. Use a negative value to disable expiration.")
        long lockTimeout() default 24L * 60L * 60L * 1000L;

ui.frontend/src/hooks/execution.ts:46

  • The LOCKED toast says “already running or stale”, but the backend returns LOCKED only when a non-expired lock is present (Locker.readLock(...) uses isLock(...) && !isExpired(...)). If the lock is stale and has an expiration, it should be removed and the run proceeds, so “stale” is misleading here.
            ToastQueue.neutral('Code execution skipped — conditions not met.', { timeout: ToastTimeoutQuick });
          } else if (queuedExecution.status === ExecutionStatus.LOCKED) {
            ToastQueue.neutral('Code execution locked — already running or stale.', { timeout: ToastTimeoutQuick });
          } else if (queuedExecution.status === ExecutionStatus.SUCCEEDED) {

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

core/src/main/java/dev/vml/es/acm/core/repo/Locker.java:83

  • lock() checks only whether a resource exists at the lock path, but Executor determines locked state via readLock()/isLockPresent(). If a non-lock resource exists at that path (e.g. missing locked property), Executor will proceed, while lock() will return early and the execution will run without any lock protection. Consider handling only real locks via isLockPresent(...) and failing fast (or explicitly cleaning up) when an unexpected resource exists.
                Resource lockCurrent = getLock(name);
                if (lockCurrent != null) {
                    if (readLock(lockCurrent).isExpired()) {
                        LOG.warn("Cannot create lock '{}' as it is stale - removing.", name);
                        resolver.delete(lockCurrent);

ui.frontend/src/hooks/execution.ts:45

  • The LOCKED status indicates a lock is held, but it doesn’t necessarily mean the script is currently running (it could be a stale lock awaiting expiration). The toast message “already running” can be misleading; consider wording it in terms of the lock being held.
            ToastQueue.neutral('Code execution locked — already running.', { timeout: ToastTimeoutQuick });

@krystian-panek-vmltech
krystian-panek-vmltech merged commit 2f7c194 into main Jul 28, 2026
1 check passed
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.

3 participants