summaryrefslogtreecommitdiffhomepage
path: root/src/lib/cache
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-04-09 20:52:18 +0900
committerAdam Malczewski <[email protected]>2026-04-09 20:52:18 +0900
commitb5a5ea8d300284e0f473df0e514cdc642857b03c (patch)
treee791331edfcb3e75885a420d4f7e8bfe9a5f0506 /src/lib/cache
parentcbf41c0e495367bb3f582ea22aabdc03bd2d046d (diff)
downloadflashair-speedsync-b5a5ea8d300284e0f473df0e514cdc642857b03c.tar.gz
flashair-speedsync-b5a5ea8d300284e0f473df0e514cdc642857b03c.zip
auto-polling of new photos
Diffstat (limited to 'src/lib/cache')
-rw-r--r--src/lib/cache/autoCacheService.ts41
1 files changed, 29 insertions, 12 deletions
diff --git a/src/lib/cache/autoCacheService.ts b/src/lib/cache/autoCacheService.ts
index e5a6584..6d29598 100644
--- a/src/lib/cache/autoCacheService.ts
+++ b/src/lib/cache/autoCacheService.ts
@@ -2,15 +2,6 @@ import { flashair } from '../flashair';
import type { FlashAirFileEntry } from '../flashair';
import { imageCache } from './imageCache';
-/**
- * Reactive state for the auto-cache background service.
- *
- * Uses Svelte 5 $state runes via the .svelte.ts convention — but since this
- * is a plain .ts file consumed by Svelte components, we store reactive values
- * in a simple mutable object that components can poll or subscribe to via
- * a wrapper. We use a manual callback approach instead.
- */
-
/** Progress of a single image being auto-cached (0–1). */
export interface AutoCacheProgress {
readonly path: string;
@@ -20,14 +11,26 @@ export interface AutoCacheProgress {
type Listener = () => void;
/**
+ * Callback invoked between each auto-cache download.
+ * The auto-cache service will wait for this to resolve before starting
+ * the next download. Used to give the poll service a chance to check
+ * for new images without HTTP contention.
+ */
+type BetweenDownloadsHook = () => Promise<void>;
+
+/**
* Singleton auto-cache service.
*
- * Call `start(images)` after loading the image list. The service will
+ * Call `start(images)` after loading the image list. The service will
* iterate newest-first, skip already-cached images, and download full-size
* images in the background one at a time.
*
* When a user-initiated download is active, call `pauseForUserDownload()`
* / `resumeAfterUserDownload()` to yield bandwidth.
+ *
+ * Set `onBetweenDownloads` to a hook that runs between each cached image.
+ * This gives external services (e.g. the poll service) a window to use the
+ * FlashAir HTTP connection without contention.
*/
class AutoCacheService {
/** Map from image path → download progress 0–1. Only contains entries being cached. */
@@ -57,6 +60,12 @@ class AutoCacheService {
/** Listeners notified on every progress change. */
private _listeners = new Set<Listener>();
+ /**
+ * Optional hook called between downloads. The service awaits this before
+ * starting the next download.
+ */
+ onBetweenDownloads: BetweenDownloadsHook | undefined;
+
/** Subscribe to state changes. Returns an unsubscribe function. */
subscribe(fn: Listener): () => void {
this._listeners.add(fn);
@@ -188,8 +197,16 @@ class AutoCacheService {
continue;
}
- // Not cached — download it
- if (this._userDownloading || !this._running) return;
+ // Not cached — run the between-downloads hook (e.g. poll check)
+ if (this.onBetweenDownloads !== undefined) {
+ try {
+ await this.onBetweenDownloads();
+ } catch {
+ // Hook failed — continue anyway
+ }
+ // Re-check state after the async hook
+ if (!this._running || this._userDownloading) return;
+ }
const success = await this._downloadImage(image);
if (success) {