Stop three enum reads escaping doWork, and pin what the attempt bound buys
Both workers read enums out of their input Data with Enum.valueOf, and all three reads sit
ABOVE the try. A name this build does not define -- which is what a downgrade or a
rollback with work still in the queue produces, since WorkManager keeps work for about a
week -- threw IllegalArgumentException straight out of doWork(). That is D13's signature
verbatim: FAILURE with reschedule = false, output Data with zero entries so the screen
says "Conversion failed." and nothing else, and no staged.delete(), so the partial stays
in cache. readSpec() twelve lines below already handles exactly this case, and its KDoc
says why.
So all three take readSpec's shape: entries.firstOrNull { it.name == name } ?: default.
Consistency argues for it as much as correctness does -- the file already contains the
right answer to this question, three times.
WorkerEnumFallbackTest reaches each read. Two of them pin the value that replaces the
unknown name rather than only that nothing threw: a quality tier falling back to something
arbitrary would convert at a setting nobody chose, and a join's format decides the
extension its output is staged with, which is where FFmpeg infers the container from. The
engine-preference case asserts through the space check instead, because predicting which
engine AUTO picks would tie the test to a routing rule it is not about. Against the
unfixed code all three fail with "No enum constant ...".
MAX_FOREGROUND_START_ATTEMPTS had no test of its value. Both existing cases are written
against the symbol, which pins the relationship and leaves the number free: changed to 2,
the job gives up about ninety seconds after process death -- exactly the long conversion
the retry exists to protect -- and all 257 tests stayed green.
The new assertion is the property the KDoc argues, not the literal: summed against
WorkRequest's own DEFAULT_BACKOFF_DELAY_MILLIS and MAX_BACKOFF_MILLIS, the attempts have
to span at least eight hours, which is what makes "the user will have opened the app by
then" a claim rather than a hope. A deliberate re-tune that keeps the property passes; the
accident does not, and reports the span it got (0.025 hours at 2).
R22 / #31, R10 / #19
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -46,9 +46,12 @@ class ConcatWorker(context: Context, params: WorkerParameters) : CoroutineWorker
|
||||
val declaredTotal = inputData
|
||||
.takeIf { it.hasKeyWithValueOfType<Long>(KEY_TOTAL_BYTES) }
|
||||
?.getLong(KEY_TOTAL_BYTES, 0L)
|
||||
val format = OutputFormat.valueOf(
|
||||
inputData.getString(KEY_FORMAT) ?: DEFAULT_FORMAT.name,
|
||||
)
|
||||
// Looked up rather than `valueOf` -- see the same three reads in ConversionWorker. This one
|
||||
// is above the try as well, so a format name this build does not define used to throw past
|
||||
// the catch: FAILED with no error in the output Data, and no staged.delete().
|
||||
val format = inputData.getString(KEY_FORMAT)
|
||||
?.let { name -> OutputFormat.entries.firstOrNull { it.name == name } }
|
||||
?: DEFAULT_FORMAT
|
||||
|
||||
if (!hasRoomFor(declaredTotal, uris)) {
|
||||
return Result.failure(workDataOf(KEY_ERROR to "Not enough free space to join these files."))
|
||||
|
||||
@@ -67,12 +67,18 @@ class ConversionWorker(context: Context, params: WorkerParameters) : CoroutineWo
|
||||
.takeIf { it.hasKeyWithValueOfType<Long>(KEY_SIZE_BYTES) }
|
||||
?.getLong(KEY_SIZE_BYTES, 0L)
|
||||
val spec = readSpec()
|
||||
val quality = QualityTier.valueOf(
|
||||
inputData.getString(KEY_QUALITY) ?: QualityTier.FAST.name,
|
||||
)
|
||||
val preference = EnginePreference.valueOf(
|
||||
inputData.getString(KEY_ENGINE_PREFERENCE) ?: EnginePreference.AUTO.name,
|
||||
)
|
||||
// Looked up rather than `valueOf`, for the reason [readSpec] gives twelve lines below and
|
||||
// for one more: these three reads sit ABOVE the try. A name this build does not define --
|
||||
// which is what a downgrade with work still queued produces, the same previous-version case
|
||||
// JobTags is written for -- threw IllegalArgumentException straight past the catch, taking
|
||||
// the retry, the error message and the staged file's delete with it. That is the escape
|
||||
// shape setForeground was moved inside the try to end.
|
||||
val quality = inputData.getString(KEY_QUALITY)
|
||||
?.let { name -> QualityTier.entries.firstOrNull { it.name == name } }
|
||||
?: QualityTier.FAST
|
||||
val preference = inputData.getString(KEY_ENGINE_PREFERENCE)
|
||||
?.let { name -> EnginePreference.entries.firstOrNull { it.name == name } }
|
||||
?: EnginePreference.AUTO
|
||||
|
||||
if (!hasRoomFor(declaredSize, inputUri)) {
|
||||
return Result.failure(workDataOf(KEY_ERROR to "Not enough free space to convert."))
|
||||
|
||||
Reference in New Issue
Block a user