From 5962d0bc683d7d04727d8e58fefb341929bb7a22 Mon Sep 17 00:00:00 2001 From: Jeremy Karlsson Date: Fri, 3 May 2024 15:00:16 +0200 Subject: [PATCH] [Player] Store data without IndexedDB (#117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * EventSessionDB only in memory * Don't emit play log event for never started preloads * rm chai? * Update packages/player/src/player/basePlayer.ts Co-authored-by: Øyvind Smestad * Add removeOldIDB method. --------- Co-authored-by: Øyvind Smestad --- packages/player/src/index.ts | 17 ++ .../src/internal/helpers/event-session.ts | 192 +----------------- packages/player/src/player/basePlayer.ts | 5 + 3 files changed, 27 insertions(+), 187 deletions(-) diff --git a/packages/player/src/index.ts b/packages/player/src/index.ts index 01e5127d..20170a3e 100644 --- a/packages/player/src/index.ts +++ b/packages/player/src/index.ts @@ -54,8 +54,25 @@ export function bootstrap(options: Options) { setPlayerConfig(options.players); } +/** + * Remove the old IDB database which was used for storing events. + */ +function removeOldIDB() { + const ssuid = localStorage.getItem('ssuid'); + + try { + if (ssuid) { + indexedDB.deleteDatabase('streaming-sessions-' + ssuid); + } + } catch (e) { + console.warn(`DB streaming-sessions-${ssuid} could not be deleted`); + console.error(e); + } +} + mountVideoElements().then().catch(console.error); activateVideoElements().then().catch(console.error); +removeOldIDB(); export * from './api/index'; export type * from './api/index'; diff --git a/packages/player/src/internal/helpers/event-session.ts b/packages/player/src/internal/helpers/event-session.ts index d361526b..f18318c6 100644 --- a/packages/player/src/internal/helpers/event-session.ts +++ b/packages/player/src/internal/helpers/event-session.ts @@ -7,65 +7,10 @@ type MaybeEvent

= | undefined; class EventSessionDB { - // @ts-expect-error - Assigned through private method #init. - #db: IDBDatabase; - // @ts-expect-error - Assigned through private method #init. - #name: string; - #openingDatabase: Promise | undefined; + #db: Map; constructor() { - this.#createNewDatabase().catch(console.error); - } - - /** - * Create a new database and set the #openingDatabase promise to undefined when it's done. - */ - async #createNewDatabase() { - this.#openingDatabase = this.#init().then(() => { - this.#openingDatabase = undefined; - }); - - return this.#openingDatabase; - } - - /** - * Ensure that the database is open and ready to use. Using a promise to - * debounce multiple calls to this method. - */ - async #ensureDatabase() { - let isExisting = false; - - if (this.#openingDatabase) { - await this.#openingDatabase; - } else { - // Attempt to open the database - this.#openingDatabase = new Promise((resolve, reject) => { - const request = window.indexedDB.open(this.#name); - - // This event means the database was found and successfully opened - request.onsuccess = () => { - isExisting = true; // Database exists - resolve(); - request.result.close(); // Close the database connection - }; - - // This event means the database does not exist and is being created - request.onupgradeneeded = () => { - isExisting = false; // Trigger database creation - }; - - request.onerror = () => { - reject(request.error); - }; - }); - - await this.#openingDatabase; - - // If database didn't exist, create it - if (!isExisting) { - await this.#createNewDatabase(); - } - } + this.#db = new Map(); } async #generateCompositeKey(streamingSessionId: string, eventName: string) { @@ -81,44 +26,6 @@ class EventSessionDB { return hashHex; } - async #init() { - return new Promise((resolve, reject) => { - this.#removeOldDatabase(); - - const uuid = crypto.randomUUID(); - const name = 'streaming-sessions-' + uuid; - this.#name = name; - const request = indexedDB.open(name, 1); - - request.onupgradeneeded = () => { - this.#db = request.result; - - if (!this.#db.objectStoreNames.contains('events')) { - this.#db.createObjectStore('events', { - keyPath: 'id', - }); - } - }; - - request.onsuccess = () => { - this.#db = request.result; - localStorage.setItem('ssuid', uuid); - - resolve(); - }; - - request.onerror = () => reject(request.error); - }); - } - - #removeOldDatabase() { - const ssuid = localStorage.getItem('ssuid'); - - if (ssuid) { - indexedDB.deleteDatabase('streaming-sessions-' + ssuid); - } - } - /** * Delete a logged event by name and streamingSessionId. */ @@ -129,39 +36,12 @@ class EventSessionDB { name: string; streamingSessionId: string; }): Promise { - await this.#ensureDatabase(); - const compositeKey = await this.#generateCompositeKey( streamingSessionId, name, ); - return new Promise((resolve, reject) => { - try { - const transaction = this.#db.transaction(['events'], 'readwrite'); - const store = transaction.objectStore('events'); - const request = store.delete(compositeKey); - - request.onsuccess = () => resolve(); - - request.onerror = () => { - throw request.error; - }; - } catch (error) { - reject(error); - } - }).catch(async error => { - if ( - error instanceof DOMException && - error.message.includes('The database connection is closing') - ) { - await this.#ensureDatabase(); - return this.delete({ - name, - streamingSessionId, - }); - } - }); + this.#db.delete(compositeKey); } /** @@ -174,46 +54,12 @@ class EventSessionDB { name: string; streamingSessionId: string; }): Promise> { - await this.#ensureDatabase(); - const compositeKey = await this.#generateCompositeKey( streamingSessionId, name, ); - return new Promise>((resolve, reject) => { - try { - const transaction = this.#db.transaction(['events'], 'readonly'); - const store = transaction.objectStore('events'); - const request = store.get(compositeKey); - - request.onsuccess = () => { - if (request.result) { - resolve(request.result as MaybeEvent

); - } else { - resolve(undefined); - } - }; - - request.onerror = () => { - throw request.error; - }; - } catch (error) { - reject(error); - } - }).catch(async error => { - if ( - error instanceof DOMException && - error.message.includes('The database connection is closing') - ) { - await this.#ensureDatabase(); - - return this.get

({ - name, - streamingSessionId, - }); - } - }); + return this.#db.get(compositeKey); } /** @@ -225,40 +71,12 @@ class EventSessionDB { payload: unknown; streamingSessionId: string; }): Promise { - await this.#ensureDatabase(); - const compositeKey = await this.#generateCompositeKey( value.streamingSessionId, value.name, ); - return new Promise((resolve, reject) => { - try { - const transaction = this.#db.transaction(['events'], 'readwrite'); - const store = transaction.objectStore('events'); - - value.id = compositeKey; - - const request = store.put(value); - - request.onsuccess = () => resolve(); - - request.onerror = () => { - throw request.error; - }; - } catch (error) { - reject(error); - } - }).catch(async error => { - if ( - error instanceof DOMException && - error.message.includes('The database connection is closing') - ) { - await this.#ensureDatabase(); - - return this.put(value); - } - }); + this.#db.set(compositeKey, value); } } diff --git a/packages/player/src/player/basePlayer.ts b/packages/player/src/player/basePlayer.ts index e6019ce9..6bd9aaa4 100644 --- a/packages/player/src/player/basePlayer.ts +++ b/packages/player/src/player/basePlayer.ts @@ -380,6 +380,11 @@ export class BasePlayer { } finishCurrentMediaProduct(endReason: EndReason) { + // A media product was loaded but never started. + if (!this.hasStarted()) { + return; + } + const cssi = this.#currentStreamingSessionId; const hasNotBeenFinished = cssi ? streamingSessionStore.hasStreamInfo(cssi)