Add message history to TreeNode

This commit is contained in:
Thomas Nordquist
2019-01-12 14:29:21 +01:00
parent a8e082f084
commit 48b7754a2b
6 changed files with 126 additions and 7 deletions

View File

@@ -1,3 +1,5 @@
export interface Message {
value?: any | undefined
length: number
received: Date
}

View File

@@ -0,0 +1,60 @@
interface Lengthwise {
length: number
}
export class RingBuffer<T extends Lengthwise> {
private capacity: number
private maxItems: number
private usage: number = 0
private items: (any)[] = []
private start: number = 0
private end: number = 0
constructor(capacity: number, maxItems = Infinity) {
this.capacity = capacity
this.maxItems = maxItems
}
public toArray() {
return this.items.slice(this.start, this.end)
}
public add(item: T) {
const size = item.length
this.enforceCapacityConstraints(size)
this.usage += size
this.items[this.end] = item
this.end += 1
}
private enforceCapacityConstraints(addedItemSize: number) {
const remainingSize = this.capacity - (this.usage + addedItemSize)
if (remainingSize < 0) {
this.freeSomeSpace(Math.abs(remainingSize))
}
while ((this.end - this.start) >= this.maxItems) {
this.dropFirst()
}
}
private freeSpace(): number {
return this.capacity - this.usage
}
private isEmpty(): boolean {
return this.usage === 0
}
private freeSomeSpace(requiredSpace: number) {
while (this.freeSpace() < requiredSpace && !this.isEmpty()) {
this.dropFirst()
}
}
private dropFirst() {
const freedSpace = this.items[this.start].length
this.usage -= freedSpace
delete this.items[this.start]
this.start += 1
}
}

View File

@@ -1,9 +1,10 @@
import { Edge, Message } from './'
import { Edge, Message, RingBuffer } from './'
import { EventDispatcher } from '../../../events'
export class TreeNode {
public sourceEdge?: Edge
public message?: Message
public messageHistory = new RingBuffer<Message>(3000, 100)
public edges: {[s: string]: Edge} = {}
public collapsed = false
public messages: number = 0
@@ -21,7 +22,7 @@ export class TreeNode {
sourceEdge.target = this
}
this.setMessage(message)
message && this.setMessage(message)
this.onMerge.subscribe(() => {
this.cachedLeafes = undefined
this.cachedLeafMessageCount = undefined
@@ -35,8 +36,9 @@ export class TreeNode {
})
}
public setMessage(value: any) {
this.message = value
public setMessage(message: Message) {
this.messageHistory.add(message)
this.message = message
this.messages += 1
}

View File

@@ -1,7 +1,11 @@
import { Edge, Message, Tree, TreeNode } from './'
import { Edge, Tree, TreeNode } from './'
interface HasLength {
length: number
}
export abstract class TreeNodeFactory {
public static fromEdgesAndValue(edgeNames: string[], value: any): TreeNode {
public static fromEdgesAndValue<T extends HasLength>(edgeNames: string[], value: T): TreeNode {
let currentNode: TreeNode = new Tree()
for (const edgeName of edgeNames) {
const edge = new Edge(edgeName)
@@ -11,7 +15,11 @@ export abstract class TreeNodeFactory {
currentNode = newNode
}
currentNode.setMessage({ value })
currentNode.setMessage({
value,
length: value.length,
received: new Date(),
})
return currentNode
}
}

View File

@@ -4,3 +4,4 @@ export { Message } from './Message'
export { TreeNodeFactory } from './TreeNodeFactory'
export { Tree } from './Tree'
export { Hashable } from './Hashable'
export * from './RingBuffer'

View File

@@ -0,0 +1,46 @@
import { RingBuffer } from '../'
import { expect } from 'chai'
import 'mocha'
describe('RingBuffer', () => {
it('should add a new value', () => {
const b = new RingBuffer(30)
b.add('hello')
expect(b.toArray()[0]).to.eq('hello')
})
it('should add a new value after the first', () => {
const b = new RingBuffer(30)
b.add('hello')
b.add('world')
expect(b.toArray()[1]).to.eq('world')
})
it('should remove old values if buffer size is reached', () => {
const b = new RingBuffer(6)
b.add('hello')
b.add('world')
expect(b.toArray()[0]).to.eq('world')
})
it('items bigger then the buffer should be stored anyway', () => {
const b = new RingBuffer(3)
b.add('hello')
expect(b.toArray()[0]).to.eq('hello')
b.add('world')
expect(b.toArray()[0]).to.eq('world')
})
it('max item count should be respected', () => {
const b = new RingBuffer(100, 3)
b.add('a')
b.add('b')
b.add('c')
b.add('d')
b.add('e')
expect(b.toArray().length).to.eq(3)
expect(b.toArray()[0]).to.eq('c')
expect(b.toArray()[1]).to.eq('d')
expect(b.toArray()[2]).to.eq('e')
})
})