A music player that connects to your cloud/distributed storage.

fix: dasl sync loop

+38 -19
+14
src/common/signal.js
··· 65 65 66 66 /** 67 67 * @template T 68 + * @param {function(): Promise<T>} fn 69 + * @returns {Promise<T>} 70 + */ 71 + export const untrackedAsync = async (fn) => { 72 + const sub = setActiveSub(void 0); 73 + try { 74 + return await fn(); 75 + } finally { 76 + setActiveSub(sub); 77 + } 78 + }; 79 + 80 + /** 81 + * @template T 68 82 * @param {{ get: SignalReader<T>; set: SignalWriter<T> }} _ 69 83 * @returns {Signal<T>} 70 84 */
+24 -19
src/components/transformer/output/bytes/dasl-sync/element.js
··· 5 5 import "@components/output/polymorphic/indexed-db/element.js"; 6 6 7 7 import * as CID from "@common/cid.js"; 8 - import { computed, signal } from "@common/signal.js"; 8 + import { computed, signal, untracked } from "@common/signal.js"; 9 9 import { compareTimestamps } from "@common/utils.js"; 10 10 import { OutputTransformer } from "../../base.js"; 11 11 import { IDB_PREFIX } from "./constants.js"; ··· 47 47 remoteState, 48 48 { saveLocal, saveRemote }, 49 49 ) => { 50 - const container = signal(/** @type {Container<T>} */ (EMPTY)); 50 + const container = signal( 51 + /** @type {Container<T>} */ (EMPTY), 52 + { compare: (a, b) => a.cid === b.cid }, 53 + ); 51 54 52 55 const isReady = signal(false); 53 - const isMerging = signal(false); 56 + const merging = signal({ isBusy: false, lastCID: "" }); 54 57 55 58 this.effect(() => { 56 59 if (!isReady.value) return; 57 - if (isMerging.value) return; 60 + if (merging.value.isBusy) return; 58 61 59 62 const lb = localCollection(); 60 63 const rb = remote.ready() ? remoteCollection() : undefined; ··· 72 75 73 76 if (remote.ready() && rs === "loaded") { 74 77 const bytes = this.save(l); 75 - saveRemote(bytes); 78 + untracked(() => saveRemote(bytes)); 76 79 } 77 80 } 78 81 } else if (!l) { ··· 80 83 81 84 const bytes = this.save(r); 82 85 saveLocal(bytes); 83 - } else { 84 - container.value = l; 86 + } else if ( 87 + rs === "loaded" && this.hasDiverged({ local: l, remote: r }) 88 + ) { 89 + untracked(() => { 90 + merging.value = { isBusy: true, lastCID: merging.value.lastCID }; 91 + }); 85 92 86 - if (this.hasDiverged({ local: l, remote: r })) { 87 - isMerging.value = true; 93 + this.merge(l, r).then(async (c) => { 94 + if (c.cid === merging.value.lastCID) return; 88 95 89 - this.merge(l, r).then(async (c) => { 90 - container.value = c; 96 + container.value = c; 91 97 92 - const bytes = this.save(c); 93 - await saveLocal(bytes); 98 + const bytes = this.save(c); 99 + await saveLocal(bytes); 94 100 95 - if (remote.ready() && rs === "loaded") { 96 - await saveRemote(bytes); 97 - } 101 + if (remote.ready() && rs === "loaded") { 102 + await untracked(() => saveRemote(bytes)); 103 + } 98 104 99 - isMerging.value = false; 100 - }); 101 - } 105 + merging.value = { isBusy: false, lastCID: c.cid ?? "" }; 106 + }); 102 107 } 103 108 }); 104 109