Skip to content

Commit

Permalink
feat: stricter typings for constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
Julusian committed Dec 3, 2019
1 parent 9102550 commit 708f9e4
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 47 deletions.
2 changes: 1 addition & 1 deletion examples/nodejs/own-class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async function runExample () {
let originalHouse = new House(['north', 'west'], ['entrance','kitchen', 'bedroom'])

// Create threaded instance of the class House:
let threadedHouse = await threadedClass<House>(HOUSE_PATH, House, [['north', 'west'], ['entrance','kitchen', 'bedroom']])
let threadedHouse = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['north', 'west'], ['entrance','kitchen', 'bedroom']])

// Print number of rooms:
console.log(originalHouse.getRooms()) // ['entrance','kitchen', 'bedroom']
Expand Down
18 changes: 9 additions & 9 deletions src/__tests__/restarting.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('restarts', () => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)
})
test('restart instance', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [])
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [])
let onClosed = jest.fn(() => {
// oh dear, the process was closed
})
Expand All @@ -47,9 +47,9 @@ describe('restarts', () => {

})
test('restart instance with multiple', async () => {
let threaded0 = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { threadUsage: 0.1 })
let threaded1 = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { threadUsage: 0.1 })
let threaded2 = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { threadUsage: 0.1 })
let threaded0 = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { threadUsage: 0.1 })
let threaded1 = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { threadUsage: 0.1 })
let threaded2 = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { threadUsage: 0.1 })
let onClosed0 = jest.fn()
let onClosed1 = jest.fn()
let onClosed2 = jest.fn()
Expand Down Expand Up @@ -94,7 +94,7 @@ describe('restarts', () => {
test('force restart', async () => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)

let thread0 = await threadedClass<House>(HOUSE_PATH, House, [['south0'], []])
let thread0 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south0'], []])
let onClosed = jest.fn()
ThreadedClassManager.onEvent(thread0, 'thread_closed', onClosed)

Expand All @@ -121,7 +121,7 @@ describe('restarts', () => {
test('child process crash', async () => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)

let thread0 = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [])
let thread0 = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [])
let onClosed = jest.fn()
ThreadedClassManager.onEvent(thread0, 'thread_closed', onClosed)

Expand All @@ -145,11 +145,11 @@ describe('restarts', () => {
test('automatic restart', async () => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)

let thread0 = await threadedClass<House>(HOUSE_PATH, House, [['south0'], []],{
let thread0 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south0'], []],{
autoRestart: true,
threadUsage: 0.5
})
let thread1 = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [],{
let thread1 = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [],{
autoRestart: true,
threadUsage: 0.5
})
Expand Down Expand Up @@ -210,7 +210,7 @@ describe('restarts', () => {
test('orphan monitoring', async () => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)

let thread1 = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [],{
let thread1 = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [],{
autoRestart: true,
threadUsage: 0.5,
freezeLimit: 200
Expand Down
68 changes: 34 additions & 34 deletions src/__tests__/test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const getTests = (disableMultithreading: boolean) => {
expect(original.getWindows('')).toHaveLength(2)
expect(original.getRooms()).toHaveLength(1)

let threaded = await threadedClass<House>(HOUSE_PATH, House, [['north', 'west'], ['south']], { disableMultithreading })
let threaded = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['north', 'west'], ['south']], { disableMultithreading })
let onClosed = jest.fn()
const onClosedListener = ThreadedClassManager.onEvent(threaded, 'thread_closed', onClosed)

Expand All @@ -58,7 +58,7 @@ const getTests = (disableMultithreading: boolean) => {

expect(original.returnValue('asdf')).toEqual('asdf')

let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let onClosed = jest.fn()
ThreadedClassManager.onEvent(threaded, 'thread_closed', onClosed)

Expand All @@ -73,7 +73,7 @@ const getTests = (disableMultithreading: boolean) => {
test('import wrong path', async () => {
let error: any = null
try {
await threadedClass<House>('./nonexistent/path', House, [[], []], { disableMultithreading })
await threadedClass<House, typeof House>('./nonexistent/path', House, [[], []], { disableMultithreading })
} catch (e) {
error = e.toString()
}
Expand All @@ -82,7 +82,7 @@ const getTests = (disableMultithreading: boolean) => {
})
test('eventEmitter', async () => {

let threaded = await threadedClass<House>(HOUSE_PATH, House, [['north', 'west'], ['south']], { disableMultithreading })
let threaded = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['north', 'west'], ['south']], { disableMultithreading })

let onEvent = jest.fn()
await threaded.on('test', onEvent)
Expand All @@ -106,7 +106,7 @@ const getTests = (disableMultithreading: boolean) => {

expect(result).toEqual('parent,child,parent2,child2')

let threaded = await threadedClass<House>(HOUSE_PATH, House, [['north', 'west'], ['south']], { disableMultithreading })
let threaded = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['north', 'west'], ['south']], { disableMultithreading })

let onEvent = jest.fn()
await threaded.on('test', onEvent)
Expand All @@ -130,7 +130,7 @@ const getTests = (disableMultithreading: boolean) => {
})
expect(original.host).toEqual('192.168.0.1')

let threaded = await threadedClass<CasparCG>('casparcg-connection', CasparCG, [{
let threaded = await threadedClass<CasparCG, typeof CasparCG>('casparcg-connection', CasparCG, [{
host: '192.168.0.1',
autoConnect: false
}], { disableMultithreading })
Expand All @@ -148,7 +148,7 @@ const getTests = (disableMultithreading: boolean) => {
let euroSign = original.end(Buffer.from([0xE2, 0x82, 0xAC]))
expect(euroSign).toEqual('€')

let threaded = await threadedClass<StringDecoder>('string_decoder', StringDecoder, ['utf8'], { disableMultithreading })
let threaded = await threadedClass<StringDecoder, typeof StringDecoder>('string_decoder', StringDecoder, ['utf8'], { disableMultithreading })

let euroSign2 = await threaded.end(Buffer.from([0xE2, 0x82, 0xAC]))

Expand Down Expand Up @@ -182,7 +182,7 @@ const getTests = (disableMultithreading: boolean) => {

for (let i = 0; i < 5; i++) {
ps.push(
threadedClass<House>(HOUSE_PATH, House, [['aa', 'bb'], []], { disableMultithreading })
threadedClass<House, typeof House>(HOUSE_PATH, House, [['aa', 'bb'], []], { disableMultithreading })
.then((myHouse) => {
threads.push(myHouse)
return myHouse.slowFib(37)
Expand All @@ -205,7 +205,7 @@ const getTests = (disableMultithreading: boolean) => {
}
test('properties', async () => {
let original = new House([], ['south'])
let threaded = await threadedClass<House>(HOUSE_PATH, House, [[], ['south']], { disableMultithreading })
let threaded = await threadedClass<House, typeof House>(HOUSE_PATH, House, [[], ['south']], { disableMultithreading })

// Method with parameter and return value:
expect(original.returnValue('myValue')).toEqual('myValue')
Expand Down Expand Up @@ -268,14 +268,14 @@ const getTests = (disableMultithreading: boolean) => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)

// threadUsage: 0.3, make room for 3 instances in each thread
let threadedHouse0 = await threadedClass<House>(HOUSE_PATH, House, [['south0'], []], { threadUsage: 0.3, disableMultithreading })
let threadedHouse0 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south0'], []], { threadUsage: 0.3, disableMultithreading })
expect(ThreadedClassManager.getThreadCount()).toEqual(1)
let threadedHouse1 = await threadedClass<House>(HOUSE_PATH, House, [['south1'], []], { threadUsage: 0.3, disableMultithreading })
let threadedHouse1 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south1'], []], { threadUsage: 0.3, disableMultithreading })
expect(ThreadedClassManager.getThreadCount()).toEqual(1)
let threadedHouse2 = await threadedClass<House>(HOUSE_PATH, House, [['south2'], []], { threadUsage: 0.3, disableMultithreading })
let threadedHouse2 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south2'], []], { threadUsage: 0.3, disableMultithreading })
expect(ThreadedClassManager.getThreadCount()).toEqual(1)

let threadedHouse3 = await threadedClass<House>(HOUSE_PATH, House, [['south3'], []], { threadUsage: 0.3, disableMultithreading })
let threadedHouse3 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south3'], []], { threadUsage: 0.3, disableMultithreading })
expect(ThreadedClassManager.getThreadCount()).toEqual(2)

// Check that all instances return correct data:
Expand Down Expand Up @@ -307,14 +307,14 @@ const getTests = (disableMultithreading: boolean) => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)

// use threadId to control which thread the instances are put in
let threadedHouse0 = await threadedClass<House>(HOUSE_PATH, House, [['south0'], []], { threadId: 'one', disableMultithreading })
let threadedHouse0 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south0'], []], { threadId: 'one', disableMultithreading })
expect(ThreadedClassManager.getThreadCount()).toEqual(1)
let threadedHouse1 = await threadedClass<House>(HOUSE_PATH, House, [['south1'], []], { threadId: 'one', disableMultithreading })
let threadedHouse1 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south1'], []], { threadId: 'one', disableMultithreading })
expect(ThreadedClassManager.getThreadCount()).toEqual(1)
let threadedHouse2 = await threadedClass<House>(HOUSE_PATH, House, [['south2'], []], { threadId: 'one', disableMultithreading })
let threadedHouse2 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south2'], []], { threadId: 'one', disableMultithreading })
expect(ThreadedClassManager.getThreadCount()).toEqual(1)

let threadedHouse3 = await threadedClass<House>(HOUSE_PATH, House, [['south3'], []], { threadId: 'two', disableMultithreading })
let threadedHouse3 = await threadedClass<House, typeof House>(HOUSE_PATH, House, [['south3'], []], { threadId: 'two', disableMultithreading })
expect(ThreadedClassManager.getThreadCount()).toEqual(2)

// Check that all instances return correct data:
Expand Down Expand Up @@ -342,7 +342,7 @@ const getTests = (disableMultithreading: boolean) => {
})

test('supported data types', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })

let values: any[] = [
null,
Expand Down Expand Up @@ -411,7 +411,7 @@ const getTests = (disableMultithreading: boolean) => {
]

for (let value of values) {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [value], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [value], { disableMultithreading })
let returned: any = await threaded.returnParam1()

if (value && typeof value === 'function') {
Expand All @@ -432,7 +432,7 @@ const getTests = (disableMultithreading: boolean) => {
for (let value of unsupportedValues) {
let returnError: any = null
try {
await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [value], { disableMultithreading })
await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [value], { disableMultithreading })
} catch (e) {
returnError = e
}
Expand All @@ -456,7 +456,7 @@ const getTests = (disableMultithreading: boolean) => {

})
// test('execute wrapped callback loaded via constructor', async () => {
// let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [
// let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [
// { fcn: (num0: number, num1: number): number => num0 + num1 + 1 }
// ], { disableMultithreading })

Expand All @@ -466,7 +466,7 @@ const getTests = (disableMultithreading: boolean) => {
// expect(ThreadedClassManager.getThreadCount()).toEqual(0)
// })
test('execute callback loaded via constructor', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [
(num0: number, num1: number): number => num0 + num1 + 1
], { disableMultithreading })

Expand All @@ -476,7 +476,7 @@ const getTests = (disableMultithreading: boolean) => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)
})
// test('execute wrapped callback loaded via function', async () => {
// let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
// let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })

// await threaded.setParam1({ fcn: (num0: number, num1: number): number => num0 + num1 + 1 })
// expect(await threaded.callParam1Function(40, 1)).toEqual(42)
Expand All @@ -485,7 +485,7 @@ const getTests = (disableMultithreading: boolean) => {
// expect(ThreadedClassManager.getThreadCount()).toEqual(0)
// })
test('execute callback loaded via function', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })

await threaded.setParam1((num0: number, num1: number): number => num0 + num1 + 1)
expect(await threaded.callParam1(40, 1)).toEqual(42)
Expand All @@ -494,7 +494,7 @@ const getTests = (disableMultithreading: boolean) => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)
})
// test('execute wrapped callback loaded via setter', async () => {
// let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
// let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })

// threaded.Param1 = Promise.resolve({ fcn: (num0: number, num1: number): Promise<number> => Promise.resolve(num0 + num1 + 1) })
// expect(await threaded.callParam1Function(40, 1)).toEqual(42)
Expand All @@ -503,7 +503,7 @@ const getTests = (disableMultithreading: boolean) => {
// expect(ThreadedClassManager.getThreadCount()).toEqual(0)
// })
test('execute callback loaded via setter', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })

threaded.Param1 = (num0: number, num1: number): Promise<number> => Promise.resolve(num0 + num1 + 1)
expect(await threaded.callParam1(40, 1)).toEqual(42)
Expand All @@ -512,7 +512,7 @@ const getTests = (disableMultithreading: boolean) => {
expect(ThreadedClassManager.getThreadCount()).toEqual(0)
})
test('functions as arguments', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })

let i = 0
const calledSecond = jest.fn((a,b) => {
Expand Down Expand Up @@ -565,7 +565,7 @@ const getTests = (disableMultithreading: boolean) => {
})

test('error handling', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })

let error: any = null

Expand Down Expand Up @@ -633,7 +633,7 @@ const getTests = (disableMultithreading: boolean) => {

})
test('logging', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })

let mockLog = jest.fn()
let orgConsoleLog = console.log
Expand All @@ -651,7 +651,7 @@ const getTests = (disableMultithreading: boolean) => {
}
})
test('EventEmitter', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })

const eventListener0 = jest.fn()
const eventListener1 = jest.fn()
Expand All @@ -672,7 +672,7 @@ const getTests = (disableMultithreading: boolean) => {

})
test('import typescript', async () => {
let threaded = await threadedClass<TestClass>(TESTCLASS_PATH_UNSYNCED, TestClass, [], { disableMultithreading })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH_UNSYNCED, TestClass, [], { disableMultithreading })

let id = await threaded.getId()

Expand All @@ -690,7 +690,7 @@ const getTests = (disableMultithreading: boolean) => {

expect(original.returnValue('asdf')).toEqual('asdf')

let threaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading, instanceName: 'myInstance' })
let threaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading, instanceName: 'myInstance' })
let onClosed = jest.fn()
ThreadedClassManager.onEvent(threaded, 'thread_closed', onClosed)

Expand Down Expand Up @@ -747,11 +747,11 @@ describe('single-thread tests', () => {
expect((original.returnValue(buf)) === buf2).toEqual(true)
expect((original.returnValue(buf)) === buf3).toEqual(false)

let singleThreaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let singleThreaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], { disableMultithreading })
let onClosed = jest.fn()
ThreadedClassManager.onEvent(singleThreaded, 'thread_closed', onClosed)

let multiThreaded = await threadedClass<TestClass>(TESTCLASS_PATH, TestClass, [], {})
let multiThreaded = await threadedClass<TestClass, typeof TestClass>(TESTCLASS_PATH, TestClass, [], {})
let onClosed2 = jest.fn()
ThreadedClassManager.onEvent(multiThreaded, 'thread_closed', onClosed2)

Expand Down
9 changes: 6 additions & 3 deletions src/threadedClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@ import {
import { ThreadedClassManagerInternal, ChildInstance, Child } from './manager'
import { isBrowser, browserSupportsWebWorkers } from './lib'

// From: https://github.com/Morglod/tsargs/blob/master/lib/ctor-args.ts
type CtorArgs<CtorT extends new (...args: any) => any> = CtorT extends new (...args: infer K) => any ? K : never

/**
* Returns an asynchronous version of the provided class
* @param orgModule Path to imported module (this is what is in the require('XX') function, or import {class} from 'XX'} )
* @param orgClass The class to be threaded
* @param constructorArgs An array of arguments to be fed into the class constructor
*/
export function threadedClass<T> (
export function threadedClass<T, TCtor extends new (...args: any) => T> (
orgModule: string,
orgClass: Function,
constructorArgs: any[],
orgClass: TCtor,
constructorArgs: CtorArgs<TCtor>,
config: ThreadedClassConfig = {}
): Promise<ThreadedClass<T>> {
let orgClassName: string = orgClass.name
Expand Down

0 comments on commit 708f9e4

Please sign in to comment.