Podcast-Artikel: Reservierung mit Gerätenamen (claim/release, deviceId pro Browser oder App)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
cedc14f714
commit
d4a47064b2
2 changed files with 21 additions and 7 deletions
|
|
@ -260,6 +260,20 @@ const send = (url, method, body) => fetch(url, {
|
|||
body: body === undefined ? undefined : JSON.stringify(body),
|
||||
});
|
||||
|
||||
// This device's name for reserving a wish (/article/claim/), kept per browser or app.
|
||||
let memDevice = '';
|
||||
export function deviceId() {
|
||||
try {
|
||||
let id = localStorage.getItem('diora-device-id');
|
||||
if (!id) { id = 'd-' + Math.random().toString(36).slice(2, 12); localStorage.setItem('diora-device-id', id); }
|
||||
return id;
|
||||
} catch (e) {
|
||||
return memDevice || (memDevice = 'd-' + Math.random().toString(36).slice(2, 12));
|
||||
}
|
||||
}
|
||||
export const claimWish = id => send('/podcasts/episodes/' + id + '/article/claim/', 'POST', {device: deviceId()});
|
||||
export const release = id => send('/podcasts/episodes/' + id + '/article/claim/', 'DELETE', {device: deviceId()});
|
||||
|
||||
async function getJson(url) {
|
||||
const r = await fetch(url, {cache: 'no-store'});
|
||||
return {status: r.status, ok: r.ok, data: r.ok ? await r.json() : null};
|
||||
|
|
@ -330,7 +344,7 @@ export async function pickUp({onState} = {}) {
|
|||
for (const wish of pending) {
|
||||
if (gaveUp.has(wish.episode_id)) { result.skipped++; continue; }
|
||||
let claim;
|
||||
try { claim = await send('/podcasts/episodes/' + wish.episode_id + '/article/claim/', 'POST', {}); } catch (e) { return result; }
|
||||
try { claim = await claimWish(wish.episode_id); } catch (e) { return result; }
|
||||
if (!claim.ok) { result.skipped++; continue; } // 409: another device has it
|
||||
try {
|
||||
const saved = await write(wish.episode_id, {onState});
|
||||
|
|
@ -339,7 +353,7 @@ export async function pickUp({onState} = {}) {
|
|||
} catch (e) {
|
||||
result.failed++;
|
||||
gaveUp.add(wish.episode_id);
|
||||
try { await send('/podcasts/episodes/' + wish.episode_id + '/article/claim/', 'DELETE'); } catch (e2) { /* it runs out in 15 minutes */ }
|
||||
try { await release(wish.episode_id); } catch (e2) { /* it runs out in 15 minutes */ }
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
|
@ -359,7 +373,7 @@ export function watch(on) {
|
|||
export const _reset = () => { running = false; gaveUp.clear(); };
|
||||
|
||||
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
||||
window.DioraPodcastArticle = {write, pickUp, watch, notifyDone, markdownToHtml, transcriptToText};
|
||||
window.DioraPodcastArticle = {write, pickUp, watch, notifyDone, claim: claimWish, release, deviceId, markdownToHtml, transcriptToText};
|
||||
window.dispatchEvent(new Event('diora-podcast-article'));
|
||||
// At the start of diora.
|
||||
setTimeout(() => { pickUp(); }, 4000);
|
||||
|
|
|
|||
|
|
@ -135,10 +135,10 @@ test('pickUp: claim, 409 skipped, failure releases the claim, notifier per succe
|
|||
});
|
||||
const r = await pa.pickUp();
|
||||
assert.deepEqual(r, {done: 1, failed: 1, skipped: 1});
|
||||
assert.ok(w.calls.includes('POST /podcasts/episodes/2/article/claim/ {}'));
|
||||
assert.ok(w.calls.some(c => /^POST \/podcasts\/episodes\/2\/article\/claim\/ \{"device":"d-/.test(c)));
|
||||
assert.ok(!w.calls.some(c => c.startsWith('GET /podcasts/episodes/2/'))); // 409: not written
|
||||
assert.ok(w.calls.includes('DELETE /podcasts/episodes/4/article/claim/')); // failed: released
|
||||
assert.ok(!w.calls.includes('DELETE /podcasts/episodes/1/article/claim/'));
|
||||
assert.ok(w.calls.some(c => c.startsWith('DELETE /podcasts/episodes/4/article/claim/'))); // failed: released
|
||||
assert.ok(!w.calls.some(c => c.startsWith('DELETE /podcasts/episodes/1/article/claim/')));
|
||||
assert.deepEqual(w.notices, ['Artikel fertig: A']);
|
||||
// The failed one is not tried again in this visit.
|
||||
const w2 = stubWorld({pending: [{episode_id: 4, title: 'Vier'}]});
|
||||
|
|
@ -168,5 +168,5 @@ test('pickUp: no key does nothing, not even a request; no second run at the same
|
|||
const b = await pa.pickUp();
|
||||
assert.deepEqual(b, {busy: true});
|
||||
assert.equal((await a).done, 1);
|
||||
assert.equal(w2.calls.filter(c => c.startsWith('POST') && c.endsWith('/claim/ {}')).length, 1);
|
||||
assert.equal(w2.calls.filter(c => c.startsWith('POST') && c.includes('/claim/ {"device":')).length, 1);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue