Skip to content

Commit

Permalink
fix: fixed memory leak in datastore
Browse files Browse the repository at this point in the history
  • Loading branch information
mint-dewit committed May 5, 2022
1 parent ebd0136 commit 8e06eb6
Showing 1 changed file with 53 additions and 53 deletions.
106 changes: 53 additions & 53 deletions packages/timeline-state-resolver/src/conductor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1093,16 +1093,19 @@ export class Conductor extends EventEmitter<ConductorEvents> {
setDepencencies(layer.content)
})

this._deviceStates[deviceId] = [
// todo - this will be a memory leak
...this._deviceStates[deviceId].filter((s) => s.time < time),
this._deviceStates[deviceId] = _.compact([
this._deviceStates[deviceId].reverse().find((s) => s.time <= this.getCurrentTime()),
...this._deviceStates[deviceId]
.reverse()
.filter((s) => s.time < time && s.time > this.getCurrentTime())
.reverse(),
{
time,
state,
dependencies,
mappings,
},
]
])

const filledState: typeof state = JSON.parse(JSON.stringify(state))
const fillState = (content: Record<string, any>) => {
Expand All @@ -1124,60 +1127,57 @@ export class Conductor extends EventEmitter<ConductorEvents> {
return this.getDevice(deviceId)?.device.handleState(filledState, mappings)
}
setDatastore(newStore: Record<string, any>) {
const allKeys = new Set([...Object.keys(newStore), ...Object.keys(this._datastore)])

const changed: string[] = []
for (const key of allKeys) {
if (this._datastore[key] !== newStore[key]) {
// it changed! let's sift through our dependencies to see if we need to do anything
Object.entries(this._deviceStates).forEach(([deviceId, states]) => {
if (states.find((state) => state.dependencies.find((deps) => deps === key))) {
changed.push(deviceId)
this._actionQueue
.add(() => {
const allKeys = new Set([...Object.keys(newStore), ...Object.keys(this._datastore)])

const changed: string[] = []
for (const key of allKeys) {
if (this._datastore[key] !== newStore[key]) {
// it changed! let's sift through our dependencies to see if we need to do anything
Object.entries(this._deviceStates).forEach(([deviceId, states]) => {
if (states.find((state) => state.dependencies.find((deps) => deps === key))) {
changed.push(deviceId)
}
})
}
})
}
}
}

this._datastore = newStore
this._datastore = newStore

for (const deviceId of changed) {
const toBeFilled = _.compact([
this._deviceStates[deviceId].reverse().find((s) => s.time <= this.getCurrentTime()), // one state before now
...this._deviceStates[deviceId].filter((s) => s.time > this.getCurrentTime()), // all states after now
])

for (const s of toBeFilled) {
const filledState: typeof s.state = JSON.parse(JSON.stringify(s.state))
const fillState = (content: Record<string, any>) => {
Object.entries(content).forEach(([index, val]) => {
if (typeof val === 'object') {
if ('_datastoreKey' in val) {
content[index] = this._datastore[val._datastoreKey] ?? val.default
} else {
// todo - can we do a tighter check
fillState(val)
}
}
})
}
Object.values(filledState.layers).forEach((layer) => {
fillState(layer.content)
})

for (const deviceId of changed) {
let hasOneBefore = false
const toBeFilled = this._deviceStates[deviceId]
.reverse()
.filter((s) => {
if (s.time > this.getCurrentTime()) {
return true
} else if (hasOneBefore === false) {
hasOneBefore = true
return true
this.getDevice(deviceId)
?.device.handleState(filledState, s.mappings)
.catch((e) => this.emit('error', 'resolveTimeline' + e + '\nStack: ' + (e as Error).stack))
}
return false
})
.reverse()

for (const s of toBeFilled) {
const filledState: typeof s.state = JSON.parse(JSON.stringify(s.state))
const fillState = (content: Record<string, any>) => {
Object.entries(content).forEach(([index, val]) => {
if (typeof val === 'object') {
if ('_datastoreKey' in val) {
content[index] = this._datastore[val._datastoreKey] ?? val.default
} else {
// todo - can we do a tighter check
fillState(val)
}
}
})
}
Object.values(filledState.layers).forEach((layer) => {
fillState(layer.content)
})

this.getDevice(deviceId)
?.device.handleState(filledState, s.mappings)
.catch((e) => this.emit('error', 'resolveTimeline' + e + '\nStack: ' + (e as Error).stack))
}
}
})
.catch((e) => {
this.emit('error', 'Caught error in setDatastore' + e)
})
}
getTimelineSize(): number {
if (this._timelineSize === undefined) {
Expand Down

0 comments on commit 8e06eb6

Please sign in to comment.