From 283e22f36bb78b7fa326e20242e191dc69ade3dd Mon Sep 17 00:00:00 2001 From: scimmia9286 Date: Wed, 8 Nov 2023 07:49:56 +0900 Subject: [PATCH 1/5] =?UTF-8?q?=E7=95=AA=E7=B5=84=E3=81=8C=E3=83=AA?= =?UTF-8?q?=E3=82=B9=E3=82=B1=E3=82=B8=E3=83=A5=E3=83=BC=E3=83=AB=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=9F=E9=9A=9B=E3=81=AB=E3=80=81=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E3=81=AA=E7=95=AA=E7=B5=84=E3=81=BE=E3=81=A7=E5=89=8A=E9=99=A4?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=82=8B=E4=B8=8D=E5=85=B7=E5=90=88=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Mirakurun/EPG.ts | 24 ++++++++++------- src/Mirakurun/Program.ts | 56 +++++++++++++++++++++++++++++++++++----- src/Mirakurun/db.ts | 4 ++- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/Mirakurun/EPG.ts b/src/Mirakurun/EPG.ts index 67f1dc07..bc194dd9 100644 --- a/src/Mirakurun/EPG.ts +++ b/src/Mirakurun/EPG.ts @@ -128,6 +128,7 @@ interface EventState { }; present?: true; + follow?: true; } // forked from rndomhack/node-aribts/blob/1e7ef94bba3d6ac26aec764bf24dde2c2852bfcb/lib/epg.js @@ -148,6 +149,7 @@ export default class EPG { } const isP = isPF && eit.section_number === 0; + const isF = isPF && eit.section_number === 1; const networkId = eit.original_network_id; @@ -178,7 +180,9 @@ export default class EPG { startAt: getTimeFromMJD(e.start_time), duration: UNKNOWN_DURATION.compare(e.duration) === 0 ? 1 : getTimeFromBCD24(e.duration), isFree: e.free_CA_mode === 0, - _pf: isPF || undefined + _pf: isPF || undefined, // for compatibility + _isPresent: isP || undefined, + _isFollowing: isF || undefined }; _.program.add(programItem); } @@ -210,19 +214,16 @@ export default class EPG { version: {}, _groups: [] }, - - present: isP || undefined + present: isP || undefined, + follow: isF || undefined }; + state.version[eit.table_id] = eit.version_number; service[e.event_id] = state; } else { state = service[e.event_id]; - if (!state.present && isP) { - state.present = true; - } - - if ((!state.present || (state.present && isP)) && isOutOfDate(eit, state.version)) { + if ((!state.present && isP) || (!state.follow && isF) || isOutOfDate(eit, state.version)) { state.version[eit.table_id] = eit.version_number; if (UNKNOWN_START_TIME.compare(e.start_time) !== 0) { @@ -230,9 +231,14 @@ export default class EPG { startAt: getTimeFromMJD(e.start_time), duration: UNKNOWN_DURATION.compare(e.duration) === 0 ? 1 : getTimeFromBCD24(e.duration), isFree: e.free_CA_mode === 0, - _pf: isPF || undefined + _pf: isPF || undefined, // for compatibility + _isPresent: isP || undefined, + _isFollowing: isF || undefined }); } + + state.present = isP || undefined; + state.follow = isF || undefined; } } diff --git a/src/Mirakurun/Program.ts b/src/Mirakurun/Program.ts index def98cf7..90561929 100644 --- a/src/Mirakurun/Program.ts +++ b/src/Mirakurun/Program.ts @@ -28,6 +28,7 @@ export function getProgramItemId(networkId: number, serviceId: number, eventId: export default class Program { private _itemMap = new Map(); + private _itemMapDeleted = new Map(); private _saveTimerId: NodeJS.Timer; private _emitTimerId: NodeJS.Timer; private _emitRunning = false; @@ -50,6 +51,9 @@ export default class Program { return; } + // purge logically deleted item + this._itemMapDeleted.delete(item.id); + if (firstAdd === false) { this._findAndRemoveConflicts(item); } @@ -68,7 +72,22 @@ export default class Program { } set(id: number, props: Partial): void { - const item = this.get(id); + let item = this.get(id); + if (!item) { + // Recovers logically deleted item if that is exsts into the tempolally collection. + item = this._itemMapDeleted.get(id) || null; + if (item) { + this._itemMap.set(item.id, item); + this._itemMapDeleted.delete(item.id); + this._emitPrograms.set(item, "update"); + this.save(); + + log.debug( + "ProgramItem#%d (networkId=%d, serviceId=%d, eventId=%d) has recoved from the logically-deleted store", + item.id, item.networkId, item.serviceId, item.eventId + ); + } + } if (item && common.updateObject(item, props) === true) { if (props.startAt || props.duration) { this._findAndRemoveConflicts(item); @@ -78,9 +97,18 @@ export default class Program { } } - remove(id: number): void { - if (this._itemMap.delete(id)) { - this.save(); + remove(id: number, logicallyDelete: boolean = false): void { + if (logicallyDelete) { + const item = this.get(id); + if (item) { + this._itemMapDeleted.set(item.id, item); + this._itemMap.delete(id); + this.save(); + } + } else { + if (this._itemMap.delete(id)) { + this.save(); + } } } @@ -88,6 +116,10 @@ export default class Program { return this._itemMap.has(id); } + isLogicallyDeleted(id: number): boolean { + return this._itemMapDeleted.has(id); + } + findByQuery(query: object): db.Program[] { return Array.from(this._itemMap.values()).filter(sift(query)); } @@ -189,9 +221,9 @@ export default class Program { (added.startAt <= item.startAt && item.startAt < addedEndAt) || (item.startAt <= added.startAt && added.startAt < itemEndAt) ) && - (!item._pf || added._pf) + (!(item._isPresent || item._isFollowing) || added._isPresent) ) { - this.remove(item.id); + this.remove(item.id, true); Event.emit("program", "remove", { id: item.id }); log.debug( @@ -227,6 +259,7 @@ export default class Program { log.debug("saving programs..."); + // TODO: Do we need to save/load logically deleted items? db.savePrograms( Array.from(this._itemMap.values()), _.configIntegrity.channels @@ -254,6 +287,17 @@ export default class Program { } } + // Perform GC for the logically-deleted store + for (const item of this._itemMapDeleted.values()) { + if ( + (item.duration === 1 ? longExp : shortExp) > (item.startAt + item.duration) || + maximum < item.startAt + ) { + ++count; + this._itemMapDeleted.delete(item.id); + } + } + setTimeout(this._gc.bind(this), this._programGCInterval); log.info("Program GC has finished and removed %d programs", count); diff --git a/src/Mirakurun/db.ts b/src/Mirakurun/db.ts index 1b317d92..dec877b9 100644 --- a/src/Mirakurun/db.ts +++ b/src/Mirakurun/db.ts @@ -64,7 +64,9 @@ export interface Program { relatedItems?: ProgramRelatedItem[]; /** (internal) indicates EIT[p/f] received */ - _pf?: true; + _pf?: true; // for compatibility + _isPresent?: true; + _isFollowing?: true; } export interface ProgramGenre { From 414b0a387183d5070895da54e3f3c25c3c9f425b Mon Sep 17 00:00:00 2001 From: scimmia9286 Date: Thu, 9 Nov 2023 17:14:55 +0900 Subject: [PATCH 2/5] Fixed typo --- src/Mirakurun/Program.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mirakurun/Program.ts b/src/Mirakurun/Program.ts index 90561929..9b404234 100644 --- a/src/Mirakurun/Program.ts +++ b/src/Mirakurun/Program.ts @@ -83,7 +83,7 @@ export default class Program { this.save(); log.debug( - "ProgramItem#%d (networkId=%d, serviceId=%d, eventId=%d) has recoved from the logically-deleted store", + "ProgramItem#%d (networkId=%d, serviceId=%d, eventId=%d) has recovered from the logically-deleted store", item.id, item.networkId, item.serviceId, item.eventId ); } From 9bbbb526e09479921167eb1d92048f06632e497d Mon Sep 17 00:00:00 2001 From: scimmia9286 Date: Wed, 15 Nov 2023 18:53:33 +0900 Subject: [PATCH 3/5] =?UTF-8?q?Fix:=20=E3=83=AA=E3=82=AB=E3=83=90=E3=83=AA?= =?UTF-8?q?=E3=83=BC=E3=81=97=E3=81=9F=E9=9A=9B=E3=81=AEEventType=E3=82=92?= =?UTF-8?q?Update=E3=81=8B=E3=82=89Create=E3=81=B8=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Mirakurun/Program.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mirakurun/Program.ts b/src/Mirakurun/Program.ts index 9b404234..0c305ae3 100644 --- a/src/Mirakurun/Program.ts +++ b/src/Mirakurun/Program.ts @@ -79,7 +79,7 @@ export default class Program { if (item) { this._itemMap.set(item.id, item); this._itemMapDeleted.delete(item.id); - this._emitPrograms.set(item, "update"); + this._emitPrograms.set(item, "create"); this.save(); log.debug( From 38bc5372ff8763c4797c92e613a8be7736ced47f Mon Sep 17 00:00:00 2001 From: scimmia9286 Date: Wed, 15 Nov 2023 18:58:26 +0900 Subject: [PATCH 4/5] =?UTF-8?q?Fix:=20=E7=B5=B1=E4=B8=80=E6=80=A7=E3=82=92?= =?UTF-8?q?=E6=8C=81=E3=81=9F=E3=81=9B=E3=82=8B=E3=81=9F=E3=82=81=E3=80=81?= =?UTF-8?q?EventState=E3=81=AE=E3=83=97=E3=83=AD=E3=83=91=E3=83=86?= =?UTF-8?q?=E3=82=A3=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Mirakurun/EPG.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Mirakurun/EPG.ts b/src/Mirakurun/EPG.ts index bc194dd9..3a636d7a 100644 --- a/src/Mirakurun/EPG.ts +++ b/src/Mirakurun/EPG.ts @@ -128,7 +128,7 @@ interface EventState { }; present?: true; - follow?: true; + following?: true; } // forked from rndomhack/node-aribts/blob/1e7ef94bba3d6ac26aec764bf24dde2c2852bfcb/lib/epg.js @@ -215,7 +215,7 @@ export default class EPG { _groups: [] }, present: isP || undefined, - follow: isF || undefined + following: isF || undefined }; state.version[eit.table_id] = eit.version_number; @@ -223,7 +223,7 @@ export default class EPG { } else { state = service[e.event_id]; - if ((!state.present && isP) || (!state.follow && isF) || isOutOfDate(eit, state.version)) { + if ((!state.present && isP) || (!state.following && isF) || isOutOfDate(eit, state.version)) { state.version[eit.table_id] = eit.version_number; if (UNKNOWN_START_TIME.compare(e.start_time) !== 0) { @@ -238,7 +238,7 @@ export default class EPG { } state.present = isP || undefined; - state.follow = isF || undefined; + state.following = isF || undefined; } } From 61b925179f2b60649ad833d7147e6c96e2de1a17 Mon Sep 17 00:00:00 2001 From: Yuki Date: Tue, 11 Feb 2025 12:38:11 +0900 Subject: [PATCH 5/5] fix spaces --- src/Mirakurun/EPG.ts | 4 ++-- src/Mirakurun/db.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mirakurun/EPG.ts b/src/Mirakurun/EPG.ts index 3a636d7a..90da32c3 100644 --- a/src/Mirakurun/EPG.ts +++ b/src/Mirakurun/EPG.ts @@ -180,7 +180,7 @@ export default class EPG { startAt: getTimeFromMJD(e.start_time), duration: UNKNOWN_DURATION.compare(e.duration) === 0 ? 1 : getTimeFromBCD24(e.duration), isFree: e.free_CA_mode === 0, - _pf: isPF || undefined, // for compatibility + _pf: isPF || undefined, // for compatibility _isPresent: isP || undefined, _isFollowing: isF || undefined }; @@ -231,7 +231,7 @@ export default class EPG { startAt: getTimeFromMJD(e.start_time), duration: UNKNOWN_DURATION.compare(e.duration) === 0 ? 1 : getTimeFromBCD24(e.duration), isFree: e.free_CA_mode === 0, - _pf: isPF || undefined, // for compatibility + _pf: isPF || undefined, // for compatibility _isPresent: isP || undefined, _isFollowing: isF || undefined }); diff --git a/src/Mirakurun/db.ts b/src/Mirakurun/db.ts index dec877b9..e6414faf 100644 --- a/src/Mirakurun/db.ts +++ b/src/Mirakurun/db.ts @@ -64,7 +64,7 @@ export interface Program { relatedItems?: ProgramRelatedItem[]; /** (internal) indicates EIT[p/f] received */ - _pf?: true; // for compatibility + _pf?: true; // for compatibility _isPresent?: true; _isFollowing?: true; }