Skip to content

Commit f3b829d

Browse files
committed
fix: ensure cleanup of some observer helpers
1 parent ecacb90 commit f3b829d

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

meteor/server/api/deviceTriggers/RundownsObserver.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,18 @@ export class RundownsObserver {
2121
#changed: ChangedHandler | undefined
2222
#cleanup: (() => void) | undefined
2323

24+
#disposed = false
25+
2426
readonly #triggerUpdateRundownContent = new PromiseDebounce(async () => {
27+
if (this.#disposed) return
28+
2529
if (!this.#changed) return
2630
this.#cleanup?.()
2731

2832
const changed = this.#changed
2933
this.#cleanup = await changed(this.rundownIds)
34+
35+
if (this.#disposed) this.#cleanup?.()
3036
}, REACTIVITY_DEBOUNCE)
3137

3238
private constructor(onChanged: ChangedHandler) {
@@ -69,6 +75,8 @@ export class RundownsObserver {
6975
}
7076

7177
public stop = (): void => {
78+
this.#disposed = true
79+
7280
this.#triggerUpdateRundownContent.cancelWaiting()
7381
this.#rundownsLiveQuery.stop()
7482
this.#changed = undefined

meteor/server/api/deviceTriggers/StudioObserver.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ export class StudioObserver extends EventEmitter {
6767

6868
#changed: ChangedHandler
6969

70+
#disposed = false
71+
7072
constructor(studioId: StudioId, onChanged: ChangedHandler) {
7173
super()
7274
this.#changed = onChanged
@@ -94,6 +96,8 @@ export class StudioObserver extends EventEmitter {
9496
activePlaylist: Pick<DBRundownPlaylist, RundownPlaylistFields>
9597
} | null
9698
): void => {
99+
if (this.#disposed) return
100+
97101
const activePlaylistId = state?.activePlaylist?._id
98102
const activationId = state?.activePlaylist?.activationId
99103
const currentRundownId =
@@ -159,6 +163,8 @@ export class StudioObserver extends EventEmitter {
159163
} | null
160164
]
161165
>(async (state): Promise<void> => {
166+
if (this.#disposed) return
167+
162168
const showStyleBaseId = state?.showStyleBase._id
163169

164170
if (showStyleBaseId === undefined || !this.nextProps?.activePlaylistId || !this.nextProps?.activationId) {
@@ -187,28 +193,30 @@ export class StudioObserver extends EventEmitter {
187193

188194
this.showStyleBaseId = showStyleBaseId
189195

190-
let cleanupChanges: (() => void) | undefined = undefined
191-
192196
this.#rundownsLiveQuery = await RundownsObserver.create(activePlaylistId, async (rundownIds) => {
193197
logger.silly(`Creating new RundownContentObserver`)
194-
const obs1 = await RundownContentObserver.create(activePlaylistId, showStyleBaseId, rundownIds, (cache) => {
195-
cleanupChanges = this.#changed(showStyleBaseId, cache)
196198

197-
return () => {
198-
void 0
199-
}
199+
const obs1 = await RundownContentObserver.create(activePlaylistId, showStyleBaseId, rundownIds, (cache) => {
200+
return this.#changed(showStyleBaseId, cache)
200201
})
201202

202203
return () => {
203204
obs1.stop()
204-
cleanupChanges?.()
205205
}
206206
})
207+
208+
if (this.#disposed) {
209+
// If we were disposed of while waiting for the observer to be created, stop it immediately
210+
this.#rundownsLiveQuery.stop()
211+
}
207212
}, REACTIVITY_DEBOUNCE)
208213

209214
public stop = (): void => {
215+
this.#disposed = true
216+
210217
this.updateShowStyle.cancelWaiting()
211218
this.#playlistInStudioLiveQuery.stop()
212219
this.updatePlaylistInStudio.cancel()
220+
this.#rundownsLiveQuery?.stop()
213221
}
214222
}

meteor/server/publications/lib/rundownsObserver.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,17 @@ export class RundownsObserver implements Meteor.LiveQueryHandle {
1717
#changed: ChangedHandler | undefined
1818
#cleanup: (() => void) | undefined
1919

20+
#disposed = false
21+
2022
readonly #triggerUpdateRundownContent = new PromiseDebounce(async () => {
23+
if (this.#disposed) return
2124
if (!this.#changed) return
2225
this.#cleanup?.()
2326

2427
const changed = this.#changed
2528
this.#cleanup = await changed(this.rundownIds)
29+
30+
if (this.#disposed) this.#cleanup?.()
2631
}, REACTIVITY_DEBOUNCE)
2732

2833
private constructor(onChanged: ChangedHandler) {
@@ -76,6 +81,8 @@ export class RundownsObserver implements Meteor.LiveQueryHandle {
7681
}
7782

7883
public stop = (): void => {
84+
this.#disposed = true
85+
7986
this.#triggerUpdateRundownContent.cancelWaiting()
8087
this.#rundownsLiveQuery.stop()
8188
this.#changed = undefined

meteor/server/publications/packageManager/expectedPackages/contentObserver.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export class ExpectedPackagesContentObserver implements Meteor.LiveQueryHandle {
2121
#partInstanceIds: PartInstanceId[] = []
2222
#partInstanceIdObserver!: ReactiveMongoObserverGroupHandle
2323

24+
#disposed = false
25+
2426
private constructor(cache: ExpectedPackagesContentCache) {
2527
this.#cache = cache
2628
}
@@ -82,6 +84,8 @@ export class ExpectedPackagesContentObserver implements Meteor.LiveQueryHandle {
8284

8385
private updatePartInstanceIds = _.debounce(
8486
Meteor.bindEnvironment(() => {
87+
if (this.#disposed) return
88+
8589
const newPartInstanceIdsSet = new Set<PartInstanceId>()
8690

8791
this.#cache.RundownPlaylists.find({}).forEach((playlist) => {
@@ -111,6 +115,8 @@ export class ExpectedPackagesContentObserver implements Meteor.LiveQueryHandle {
111115
}
112116

113117
public stop = (): void => {
118+
this.#disposed = true
119+
114120
this.#observers.forEach((observer) => observer.stop())
115121
}
116122
}

meteor/server/publications/pieceContentStatusUI/bucket/bucketContentObserver.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export class BucketContentObserver implements Meteor.LiveQueryHandle {
3333
#showStyleBaseIds: ShowStyleBaseId[] = []
3434
#showStyleBaseIdObserver!: ReactiveMongoObserverGroupHandle
3535

36+
#disposed = false
37+
3638
private constructor(cache: BucketContentCache) {
3739
this.#cache = cache
3840
}
@@ -111,6 +113,8 @@ export class BucketContentObserver implements Meteor.LiveQueryHandle {
111113

112114
private updateShowStyleBaseIds = _.debounce(
113115
Meteor.bindEnvironment(() => {
116+
if (this.#disposed) return
117+
114118
const newShowStyleBaseIdsSet = new Set<ShowStyleBaseId>()
115119
this.#cache.BucketAdLibs.find({}).forEach((adlib) => newShowStyleBaseIdsSet.add(adlib.showStyleBaseId))
116120
this.#cache.BucketAdLibActions.find({}).forEach((action) =>
@@ -133,6 +137,8 @@ export class BucketContentObserver implements Meteor.LiveQueryHandle {
133137
}
134138

135139
public stop = (): void => {
140+
this.#disposed = true
141+
136142
this.#observers.forEach((observer) => observer.stop())
137143
}
138144
}

0 commit comments

Comments
 (0)