Skip to content

[Feature][High] Fix concurrency bugs: prefetch race condition, transaction observable leak, media store crash #3394

@numbers-official

Description

@numbers-official

Summary

Three high-priority reliability issues involving concurrency, observable management, and error recovery in core shared services.


1. Race Condition in Prefetching Service

File: src/app/shared/dia-backend/asset/prefetching/dia-backend-asset-prefetching.service.ts
Lines: 35-46

Promise.all() runs concurrent downloads that mutate a shared currentCount variable. Concurrent callback executions can cause out-of-order or skipped progress counts.

await Promise.all(
  diaBackendAssets.map(async diaBackendAsset => {
    // ... download logic ...
    currentCount += 1;  // Race condition: concurrent writes
    onStored(currentCount, totalCount);
  })
);

Fix: Use sequential for...of processing or an atomic counter pattern to ensure deterministic progress reporting.


2. Observable Memory Leak in Transaction Repository

File: src/app/shared/dia-backend/transaction/dia-backend-transaction-repository.service.ts
Lines: 55-90

The downloadExpired$ observable chain combines multiple sources and chains concatMap() operations without any catchError() operator. Failed transaction downloads can leave hanging subscriptions and partial state in parent components.

Fix: Add catchError() at the end of the observable chain with proper fallback behavior. Log errors to observability system.


3. Missing Error Recovery in Media Store

File: src/app/shared/media/media-store/media-store.service.ts
Lines: 265-273

getUrl() has no error handling for Capacitor.convertFileSrc() failures or invalid file system data. Missing/corrupted media silently breaks the display pipeline.

async getUrl(index: string, mimeType: MimeType) {
  if (Capacitor.isNativePlatform()) {
    await this.fixIncorrectExtension(index, mimeType);
    return Capacitor.convertFileSrc(await this.getUri(index));  // No try-catch
  }
  return URL.createObjectURL(
    await base64ToBlob(await this.readWithFileSystem(index), mimeType)  // No error handling
  );
}

Fix: Wrap in try-catch, return placeholder on failure, implement retry for transient file system errors.

Expected Impact

  • Accurate progress reporting during prefetch operations
  • Prevent memory accumulation from leaked observables
  • Graceful media display fallback instead of silent crashes

Generated by Heart Beat with Omni

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions