Address review feedback (@marcelklehr, Copilot):
- lockTask claims only SCHEDULED tasks (was status != RUNNING) and stamps
started_at in the same atomic UPDATE, so a finished task cannot be re-claimed
and the external-provider claim path records started_at as well.
- claimWithBoundedRetry re-reads after lockTask instead of a follow-up UPDATE.
- Oracle joins SQLite on the bounded-retry fallback: Oracle cannot combine a
row-limiting clause with FOR UPDATE (ORA-02014), which failed the claim tests
on Oracle CI.
- Reword the worker docblock/comments to "prefer oldest available" (parallel
SKIP LOCKED does not guarantee a strict global order).
- Add a regression test that lockTask does not resurrect a finished task.
Signed-off-by: Yoan Bozhilov <bygadd@gmail.com>
Assisted-by: Claude Code:claude-opus-4-8
Replace the worker retry/ignore-list claim-loop with a single atomic
SELECT ... FOR UPDATE SKIP LOCKED claim (SQLite bounded-retry fallback),
preserving the no-duplicate guarantee while removing the thundering-herd
contention that throttled backlog draining. Add a (status,type,last_updated)
index via the table-creating migration + db:add-missing-indices listener.
Signed-off-by: Yoan Bozhilov <bygadd@gmail.com>
Assisted-by: Claude Code:claude-opus-4-8
When decrypting a v3 ciphertext with a mismatched secret, the first
attempt throws an Exception (HMAC mismatch). The fallback then calls
decryptWithoutSecret() with an empty string, which causes hash_hkdf()
to throw a ValueError. Since ValueError extends \Error rather than
\Exception, it bypassed the catch block and propagated as an unhandled
error, crashing the whole request.
Wrap the fallback in its own try/catch(\Throwable) and rethrow the
original Exception so callers get a meaningful HMAC mismatch error.
Signed-off-by: Anna Larch <anna@nextcloud.com>
AI-Assisted-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The manager itself does not need to know what hardcoded-things an app provides,
instead the apps itself should handle this.
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
When an ownCloud-migrated group share (which has no per-user USERGROUP
subshare) is renamed for the first time, DefaultShareProvider::move()
inserted a new USERGROUP row without setting `accepted`. The column
defaulted to 0 (STATUS_PENDING), causing MountProvider to skip the
share on the next login — the shared file disappeared for the recipient.
Fix: set accepted = STATUS_ACCEPTED explicitly on the INSERT in
DefaultShareProvider::move() for the TYPE_GROUP branch.
Secondary fix: SharedMount::moveMount() silently returned true when
updateFileTarget() threw (e.g. group no longer exists on an OC-migrated
instance). Set $result = false in the catch block so View::rename()
propagates the failure instead of silently corrupting VFS state.
An opt-in occ command (sharing:fix-owncloud-group-shares) with --dry-run
support is included to repair existing broken instances. It targets only
TYPE_USERGROUP subshares with accepted=STATUS_PENDING and permissions!=0
(shares that were accepted but broken by the missing column default),
leaving explicitly declined shares (permissions=0) untouched.
AI-Assisted-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Anna Larch <anna@nextcloud.com>
AppConfig and UserConfig unconditionally queried NC-only columns (type,
lazy, flags, indexed) that don't exist in ownCloud's database schema,
breaking ownCloud → Nextcloud upgrades entirely before the schema
migration steps could run.
Restore the fallback pattern in both classes: on first loadConfig() call,
if a DBException with REASON_INVALID_FIELD_NAME is thrown, set
$migrationCompleted = false and retry selecting only the columns present
in ownCloud's schema. INSERT and UPDATE statements also omit NC-only
columns when $migrationCompleted is false.
The catch block also guards against infinite recursion: if $migrationCompleted
is already false when the exception fires, the exception is re-thrown
instead of triggering another recursive call.
Fixes: https://github.com/nextcloud/server/issues/57340
Signed-off-by: Anna Larch <anna@nextcloud.com>
AI-Assisted-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PHPUnit's enforceTimeLimit was disabled, meaning the timeoutForSmallTests,
timeoutForMediumTests and timeoutForLargeTests config values had no effect.
Enable enforcement and set realistic limits: 60s/300s/600s for
small/medium/large, with a 300s default for unannotated tests.
Also clear disable_functions in the PHP development ini preset across all
PHPUnit workflows so pcntl_signal is available — without it the signal
handler that drives timeout enforcement cannot be registered.
Signed-off-by: Anna Larch <anna@nextcloud.com>
AI-Assisted-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Anna Larch <anna@nextcloud.com>
Replace assertTrue(true), addToAssertionCount(1) and delete-without-assert
patterns with meaningful assertions or proper test removal.
Signed-off-by: Anna Larch <anna@nextcloud.com>
AI-Assisted-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eight test classes overrode tearDown() for custom DB cleanup but never
called parent::tearDown(). TestCase::tearDown() does three things these
tests were silently skipping after every test method:
- ILockingProvider::releaseAll() — unreleased locks bleed into subsequent
tests and can cause deadlocks or unexpected NotFoundException
- Storage::getGlobalCache()->clearCache() — stale filecache entries from
share/storage tests cause unrelated ObjectStore tests to receive false
from fopen() (fseek() then fails with "Argument must be of type resource")
- UserMountCache::flush() — stale mount cache causes share lookups in
later tests to fail with ShareNotFound
AI-Assisted-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Anna Larch <anna@nextcloud.com>
- Attempt delete before logging the warning, so the warning only fires
when we know recovery will succeed
- Log an error (not silently return) when delete itself fails
- Use catch (\Exception) without variable (PHP 8)
- Replace willReturnArgument(1) with explicit willReturn(true) in test
- Add blank lines between logical blocks in test for readability
Signed-off-by: Anna Larch <anna@nextcloud.com>
AI-Assisted-By: Claude Sonnet 4.6 <noreply@anthropic.com>