diff --git a/README.md b/README.md index 879c19a50..3686446fc 100644 --- a/README.md +++ b/README.md @@ -127,8 +127,14 @@ TODO TODO +#### How VM Extensions Work + +TODO + ### Plugins vs. plugin configs +### End Notes + An `organization_id` is tied to a _company_ and its _installed plugins_, a `team_id` is tied to a _project_ and its _plugin configs_ (enabled/disabled+extra config). ## Questions? diff --git a/benchmarks/vm/memory.benchmark.ts b/benchmarks/vm/memory.benchmark.ts index 885c32ed0..ebb353b4f 100644 --- a/benchmarks/vm/memory.benchmark.ts +++ b/benchmarks/vm/memory.benchmark.ts @@ -96,7 +96,7 @@ test('test vm memory usage', async () => { for (let i = 0; i < numEventsPerVM; i++) { for (let j = 0; j < numVMs; j++) { - await vms[j].methods.processEvent(createEvent(i + j)) + await vms[j].methods.processEvent!(createEvent(i + j)) } if (debug || i === numEventsPerVM - 1) { global?.gc?.() diff --git a/src/types.ts b/src/types.ts index fc535cb2d..23e1f0c5c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -161,7 +161,13 @@ export interface Plugin { from_web?: boolean created_at: string updated_at: string - capabilities?: Record + capabilities?: PluginCapabilities +} + +export interface PluginCapabilities { + jobs?: string[] + scheduled_tasks?: string[] + methods?: string[] } export interface PluginConfig { @@ -255,13 +261,13 @@ export type WorkerMethods = { export interface PluginConfigVMReponse { vm: VM methods: { - setupPlugin: () => Promise - teardownPlugin: () => Promise - onEvent: (event: PluginEvent) => Promise - onSnapshot: (event: PluginEvent) => Promise - processEvent: (event: PluginEvent) => Promise + setupPlugin?: () => Promise + teardownPlugin?: () => Promise + onEvent?: (event: PluginEvent) => Promise + onSnapshot?: (event: PluginEvent) => Promise + processEvent?: (event: PluginEvent) => Promise // DEPRECATED - processEventBatch: (batch: PluginEvent[]) => Promise + processEventBatch?: (batch: PluginEvent[]) => Promise } tasks: Record> } diff --git a/src/utils/db/sql.ts b/src/utils/db/sql.ts index 2ffd2fd31..39ee940fe 100644 --- a/src/utils/db/sql.ts +++ b/src/utils/db/sql.ts @@ -2,6 +2,7 @@ import { Hub, Plugin, PluginAttachmentDB, + PluginCapabilities, PluginConfig, PluginConfigId, PluginError, @@ -22,8 +23,8 @@ function pluginConfigsInForceQuery(specificField?: keyof PluginConfig): string { )` } -export async function getPluginRows(server: Hub): Promise { - const { rows: pluginRows }: { rows: Plugin[] } = await server.db.postgresQuery( +export async function getPluginRows(hub: Hub): Promise { + const { rows: pluginRows }: { rows: Plugin[] } = await hub.db.postgresQuery( `SELECT posthog_plugin.* FROM posthog_plugin WHERE id IN (${pluginConfigsInForceQuery('plugin_id')} GROUP BY posthog_pluginconfig.plugin_id)`, undefined, @@ -32,8 +33,8 @@ export async function getPluginRows(server: Hub): Promise { return pluginRows } -export async function getPluginAttachmentRows(server: Hub): Promise { - const { rows }: { rows: PluginAttachmentDB[] } = await server.db.postgresQuery( +export async function getPluginAttachmentRows(hub: Hub): Promise { + const { rows }: { rows: PluginAttachmentDB[] } = await hub.db.postgresQuery( `SELECT posthog_pluginattachment.* FROM posthog_pluginattachment WHERE plugin_config_id IN (${pluginConfigsInForceQuery('id')})`, undefined, @@ -42,8 +43,8 @@ export async function getPluginAttachmentRows(server: Hub): Promise { - const { rows }: { rows: PluginConfig[] } = await server.db.postgresQuery( +export async function getPluginConfigRows(hub: Hub): Promise { + const { rows }: { rows: PluginConfig[] } = await hub.db.postgresQuery( pluginConfigsInForceQuery(), undefined, 'getPluginConfigRows' @@ -51,30 +52,38 @@ export async function getPluginConfigRows(server: Hub): Promise return rows } -export async function setError( - server: Hub, - pluginError: PluginError | null, - pluginConfig: PluginConfig +export async function setPluginCapabilities( + hub: Hub, + pluginConfig: PluginConfig, + capabilities: PluginCapabilities ): Promise { - await server.db.postgresQuery( + await hub.db.postgresQuery( + 'UPDATE posthog_plugin SET capabilities = ($1) WHERE id = $2', + [capabilities, pluginConfig.plugin_id], + 'setPluginCapabilities' + ) +} + +export async function setError(hub: Hub, pluginError: PluginError | null, pluginConfig: PluginConfig): Promise { + await hub.db.postgresQuery( 'UPDATE posthog_pluginconfig SET error = $1 WHERE id = $2', [pluginError, typeof pluginConfig === 'object' ? pluginConfig?.id : pluginConfig], 'updatePluginConfigError' ) if (pluginError) { - await server.db.createPluginLogEntry( + await hub.db.createPluginLogEntry( pluginConfig, PluginLogEntrySource.Plugin, PluginLogEntryType.Error, pluginError.message, - server.instanceId, + hub.instanceId, pluginError.time ) } } -export async function disablePlugin(server: Hub, pluginConfigId: PluginConfigId): Promise { - await server.db.postgresQuery( +export async function disablePlugin(hub: Hub, pluginConfigId: PluginConfigId): Promise { + await hub.db.postgresQuery( `UPDATE posthog_pluginconfig SET enabled='f' WHERE id=$1 AND enabled='t'`, [pluginConfigId], 'disablePlugin' diff --git a/src/worker/plugins/run.ts b/src/worker/plugins/run.ts index 3f88e7831..ac4574ffa 100644 --- a/src/worker/plugins/run.ts +++ b/src/worker/plugins/run.ts @@ -66,7 +66,7 @@ export async function runProcessEvent(server: Hub, event: PluginEvent): Promise< try { returnedEvent = (await processEvent(returnedEvent)) || null - if (returnedEvent.team_id != teamId) { + if (returnedEvent.team_id !== teamId) { returnedEvent.team_id = teamId throw new IllegalOperationError('Plugin tried to change event.team_id') } diff --git a/src/worker/plugins/setup.ts b/src/worker/plugins/setup.ts index 0e0f71ec7..b5f04cf7f 100644 --- a/src/worker/plugins/setup.ts +++ b/src/worker/plugins/setup.ts @@ -9,7 +9,6 @@ import { teardownPlugins } from './teardown' export async function setupPlugins(server: Hub): Promise { const { plugins, pluginConfigs, pluginConfigsPerTeam } = await loadPluginsFromDB(server) - const pluginVMLoadPromises: Array> = [] for (const [id, pluginConfig] of pluginConfigs) { const plugin = plugins.get(pluginConfig.plugin_id) diff --git a/src/worker/vm/lazy.ts b/src/worker/vm/lazy.ts index 942ee919a..def4682f8 100644 --- a/src/worker/vm/lazy.ts +++ b/src/worker/vm/lazy.ts @@ -1,5 +1,8 @@ +import equal from 'fast-deep-equal' + import { Hub, + PluginCapabilities, PluginConfig, PluginConfigVMReponse, PluginLogEntrySource, @@ -8,41 +11,42 @@ import { PluginTaskType, } from '../../types' import { clearError, processError } from '../../utils/db/error' -import { disablePlugin } from '../../utils/db/sql' +import { disablePlugin, setPluginCapabilities } from '../../utils/db/sql' import { status } from '../../utils/status' import { createPluginConfigVM } from './vm' export class LazyPluginVM { - initialize?: (server: Hub, pluginConfig: PluginConfig, indexJs: string, logInfo: string) => Promise + initialize?: (hub: Hub, pluginConfig: PluginConfig, indexJs: string, logInfo: string) => Promise failInitialization?: () => void resolveInternalVm: Promise constructor() { this.resolveInternalVm = new Promise((resolve) => { - this.initialize = async (server: Hub, pluginConfig: PluginConfig, indexJs: string, logInfo = '') => { + this.initialize = async (hub: Hub, pluginConfig: PluginConfig, indexJs: string, logInfo = '') => { try { - const vm = await createPluginConfigVM(server, pluginConfig, indexJs) - await server.db.createPluginLogEntry( + const vm = await createPluginConfigVM(hub, pluginConfig, indexJs) + await hub.db.createPluginLogEntry( pluginConfig, PluginLogEntrySource.System, PluginLogEntryType.Info, - `Plugin loaded (instance ID ${server.instanceId}).`, - server.instanceId + `Plugin loaded (instance ID ${hub.instanceId}).`, + hub.instanceId ) status.info('🔌', `Loaded ${logInfo}`) - void clearError(server, pluginConfig) + void clearError(hub, pluginConfig) + await this.inferPluginCapabilities(hub, pluginConfig, vm) resolve(vm) } catch (error) { - await server.db.createPluginLogEntry( + await hub.db.createPluginLogEntry( pluginConfig, PluginLogEntrySource.System, PluginLogEntryType.Error, - `Plugin failed to load and was disabled (instance ID ${server.instanceId}).`, - server.instanceId + `Plugin failed to load and was disabled (instance ID ${hub.instanceId}).`, + hub.instanceId ) status.warn('⚠️', `Failed to load ${logInfo}`) - void disablePlugin(server, pluginConfig.id) - void processError(server, pluginConfig, error) + void disablePlugin(hub, pluginConfig.id) + void processError(hub, pluginConfig, error) resolve(null) } } @@ -79,4 +83,49 @@ export class LazyPluginVM { async getTasks(type: PluginTaskType): Promise> { return (await this.resolveInternalVm)?.tasks?.[type] || {} } + + private async inferPluginCapabilities( + hub: Hub, + pluginConfig: PluginConfig, + vm: PluginConfigVMReponse + ): Promise { + if (!pluginConfig.plugin) { + throw new Error(`'PluginConfig missing plugin: ${pluginConfig}`) + } + + const capabilities: Required = { scheduled_tasks: [], jobs: [], methods: [] } + + const tasks = vm?.tasks + const methods = vm?.methods + + if (methods) { + for (const [key, value] of Object.entries(methods)) { + if (value) { + capabilities.methods.push(key) + } + } + } + + if (tasks?.schedule) { + for (const [key, value] of Object.entries(tasks.schedule)) { + if (value) { + capabilities.scheduled_tasks.push(key) + } + } + } + + if (tasks?.job) { + for (const [key, value] of Object.entries(tasks.job)) { + if (value) { + capabilities.jobs.push(key) + } + } + } + + const prevCapabilities = pluginConfig.plugin.capabilities + if (!equal(prevCapabilities, capabilities)) { + await setPluginCapabilities(hub, pluginConfig, capabilities) + pluginConfig.plugin.capabilities = capabilities + } + } } diff --git a/tests/helpers/plugins.ts b/tests/helpers/plugins.ts index d67ec9903..5d23b942d 100644 --- a/tests/helpers/plugins.ts +++ b/tests/helpers/plugins.ts @@ -48,7 +48,7 @@ export const plugin60: Plugin = { is_preinstalled: false, created_at: new Date().toISOString(), updated_at: new Date().toISOString(), - capabilities: {}, + capabilities: {}, // inferred on setup } export const pluginAttachment1: PluginAttachmentDB = { @@ -139,3 +139,11 @@ export function mockPluginTempFolder(indexJs: string, pluginJson?: string): [Plu }, ] } + +export const mockPluginSourceCode = (indexJs: string): Plugin => ({ + ...plugin60, + archive: null, + plugin_type: 'source', + url: undefined, + source: indexJs, +}) diff --git a/tests/helpers/sql.ts b/tests/helpers/sql.ts index 61070a7eb..a8386a4c0 100644 --- a/tests/helpers/sql.ts +++ b/tests/helpers/sql.ts @@ -71,8 +71,15 @@ async function insertRow(db: Pool, table: string, object: Record): const params = Object.keys(object) .map((_, i) => `\$${i + 1}`) .join(',') + const values = Object.values(object).map((value) => { + if (Array.isArray(value) && value.length > 0) { + return JSON.stringify(value) + } + return value + }) + try { - await db.query(`INSERT INTO ${table} (${keys}) VALUES (${params})`, Object.values(object)) + await db.query(`INSERT INTO ${table} (${keys}) VALUES (${params})`, values) } catch (error) { console.error(`Error on table ${table} when inserting object:\n`, object, '\n', error) throw error @@ -124,11 +131,11 @@ export async function createUserTeamAndOrganization( organization_id: organizationId, app_urls: [], name: 'TEST PROJECT', - event_names: JSON.stringify([]), - event_names_with_usage: JSON.stringify([]), - event_properties: JSON.stringify([]), - event_properties_with_usage: JSON.stringify([]), - event_properties_numerical: JSON.stringify([]), + event_names: [], + event_names_with_usage: [], + event_properties: [], + event_properties_with_usage: [], + event_properties_numerical: [], created_at: new Date().toISOString(), updated_at: new Date().toISOString(), anonymize_ips: false, @@ -142,7 +149,7 @@ export async function createUserTeamAndOrganization( api_token: `THIS IS NOT A TOKEN FOR TEAM ${teamId}`, test_account_filters: [], timezone: 'UTC', - data_attributes: JSON.stringify(['data-attr']), + data_attributes: ['data-attr'], }) } diff --git a/tests/helpers/sqlMock.ts b/tests/helpers/sqlMock.ts index 33c41ef60..33ba33cba 100644 --- a/tests/helpers/sqlMock.ts +++ b/tests/helpers/sqlMock.ts @@ -9,5 +9,8 @@ export const getPluginAttachmentRows = (s.getPluginAttachmentRows as unknown) as export const getPluginConfigRows = (s.getPluginConfigRows as unknown) as jest.MockedFunction< UnPromisify > +export const setPluginCapabilities = (s.setPluginCapabilities as unknown) as jest.MockedFunction< + UnPromisify +> export const setError = (s.setError as unknown) as jest.MockedFunction> export const disablePlugin = (s.disablePlugin as unknown) as jest.MockedFunction> diff --git a/tests/plugins.test.ts b/tests/plugins.test.ts index 5dfc0d183..e500d5a25 100644 --- a/tests/plugins.test.ts +++ b/tests/plugins.test.ts @@ -9,6 +9,7 @@ import { IllegalOperationError, runProcessEvent, runProcessEventBatch } from '.. import { loadSchedule, setupPlugins } from '../src/worker/plugins/setup' import { commonOrganizationId, + mockPluginSourceCode, mockPluginTempFolder, mockPluginWithArchive, plugin60, @@ -16,7 +17,7 @@ import { pluginConfig39, } from './helpers/plugins' import { resetTestDatabase } from './helpers/sql' -import { getPluginAttachmentRows, getPluginConfigRows, getPluginRows } from './helpers/sqlMock' +import { getPluginAttachmentRows, getPluginConfigRows, getPluginRows, setPluginCapabilities } from './helpers/sqlMock' jest.mock('../src/utils/db/sql') jest.mock('../src/utils/status') @@ -40,7 +41,7 @@ afterEach(async () => { }) test('setupPlugins and runProcessEvent', async () => { - getPluginRows.mockReturnValueOnce([plugin60]) + getPluginRows.mockReturnValueOnce([{ ...plugin60 }]) getPluginAttachmentRows.mockReturnValueOnce([pluginAttachment1]) getPluginConfigRows.mockReturnValueOnce([pluginConfig39]) @@ -51,7 +52,6 @@ test('setupPlugins and runProcessEvent', async () => { expect(getPluginAttachmentRows).toHaveBeenCalled() expect(getPluginConfigRows).toHaveBeenCalled() - expect(Array.from(plugins.entries())).toEqual([[60, plugin60]]) expect(Array.from(pluginConfigs.keys())).toEqual([39]) const pluginConfig = pluginConfigs.get(39)! @@ -82,9 +82,21 @@ test('setupPlugins and runProcessEvent', async () => { 'teardownPlugin', ]) + // async loading of capabilities + expect(setPluginCapabilities).toHaveBeenCalled() + expect(Array.from(plugins.entries())).toEqual([ + [ + 60, + { + ...plugin60, + capabilities: { jobs: [], scheduled_tasks: [], methods: ['processEvent', 'processEventBatch'] }, + }, + ], + ]) + expect(clearError).toHaveBeenCalledWith(hub, pluginConfig) - const processEvent = vm!.methods['processEvent'] + const processEvent = vm!.methods['processEvent']! const event = { event: '$test', properties: {}, team_id: 2 } as PluginEvent await processEvent(event) @@ -475,6 +487,117 @@ test('plugin config order', async () => { expect(returnedEvent2!.properties!.plugins).toEqual([61, 60, 62]) }) +test('plugin with archive loads capabilities', async () => { + getPluginRows.mockReturnValueOnce([ + mockPluginWithArchive(` + function setupPlugin (meta) { meta.global.key = 'value' } + function processEvent (event, meta) { event.properties={"x": 1}; return event } + `), + ]) + getPluginConfigRows.mockReturnValueOnce([pluginConfig39]) + getPluginAttachmentRows.mockReturnValueOnce([pluginAttachment1]) + + await setupPlugins(hub) + const { pluginConfigs } = hub + + const pluginConfig = pluginConfigs.get(39)! + + await pluginConfig.vm?.resolveInternalVm + // async loading of capabilities + + expect(pluginConfig.plugin!.capabilities!.methods!.sort()).toEqual([ + 'processEvent', + 'processEventBatch', + 'setupPlugin', + ]) + expect(pluginConfig.plugin!.capabilities!.jobs).toHaveLength(0) + expect(pluginConfig.plugin!.capabilities!.scheduled_tasks).toHaveLength(0) +}) + +test('plugin with archive loads all capabilities, no random caps', async () => { + getPluginRows.mockReturnValueOnce([ + mockPluginWithArchive(` + function processEvent (event, meta) { event.properties={"x": 1}; return event } + function randomFunction (event, meta) { return event} + function onEvent (event, meta) { return event } + + function runEveryHour(meta) {console.log('1')} + + export const jobs = { + x: (event, meta) => console.log(event) + } + `), + ]) + getPluginConfigRows.mockReturnValueOnce([pluginConfig39]) + getPluginAttachmentRows.mockReturnValueOnce([pluginAttachment1]) + + await setupPlugins(hub) + const { pluginConfigs } = hub + + const pluginConfig = pluginConfigs.get(39)! + + await pluginConfig.vm?.resolveInternalVm + // async loading of capabilities + + expect(pluginConfig.plugin!.capabilities!.methods!.sort()).toEqual(['onEvent', 'processEvent', 'processEventBatch']) + expect(pluginConfig.plugin!.capabilities!.jobs).toEqual(['x']) + expect(pluginConfig.plugin!.capabilities!.scheduled_tasks).toEqual(['runEveryHour']) +}) + +test('plugin with source file loads capabilities', async () => { + const [plugin, unlink] = mockPluginTempFolder(` + function processEvent (event, meta) { event.properties={"x": 1}; return event } + function randomFunction (event, meta) { return event} + function onEvent (event, meta) { return event } + `) + + getPluginRows.mockReturnValueOnce([plugin]) + getPluginConfigRows.mockReturnValueOnce([pluginConfig39]) + getPluginAttachmentRows.mockReturnValueOnce([pluginAttachment1]) + + await setupPlugins(hub) + const { pluginConfigs } = hub + + const pluginConfig = pluginConfigs.get(39)! + + await pluginConfig.vm?.resolveInternalVm + // async loading of capabilities + + expect(pluginConfig.plugin!.capabilities!.methods!.sort()).toEqual(['onEvent', 'processEvent', 'processEventBatch']) + expect(pluginConfig.plugin!.capabilities!.jobs).toEqual([]) + expect(pluginConfig.plugin!.capabilities!.scheduled_tasks).toEqual([]) + + unlink() +}) + +test('plugin with source code loads capabilities', async () => { + const source_code = ` + function processEvent (event, meta) { event.properties={"x": 1}; return event } + function randomFunction (event, meta) { return event} + function onSnapshot (event, meta) { return event } + ` + getPluginRows.mockReturnValueOnce([mockPluginSourceCode(source_code)]) + + getPluginConfigRows.mockReturnValueOnce([pluginConfig39]) + getPluginAttachmentRows.mockReturnValueOnce([pluginAttachment1]) + + await setupPlugins(hub) + const { pluginConfigs } = hub + + const pluginConfig = pluginConfigs.get(39)! + + await pluginConfig.vm?.resolveInternalVm + // async loading of capabilities + + expect(pluginConfig.plugin!.capabilities!.methods!.sort()).toEqual([ + 'onSnapshot', + 'processEvent', + 'processEventBatch', + ]) + expect(pluginConfig.plugin!.capabilities!.jobs).toEqual([]) + expect(pluginConfig.plugin!.capabilities!.scheduled_tasks).toEqual([]) +}) + test('reloading plugins after config changes', async () => { const makePlugin = (id: number, updated_at = '2020-11-02'): any => ({ ...plugin60, @@ -549,10 +672,56 @@ test('reloading plugins after config changes', async () => { ]) }) +test("capabilities don't reload without changes", async () => { + getPluginRows.mockReturnValueOnce([{ ...plugin60 }]).mockReturnValueOnce([ + { + ...plugin60, + capabilities: { jobs: [], scheduled_tasks: [], methods: ['processEvent', 'processEventBatch'] }, + }, + ]) // updated in DB via first `setPluginCapabilities` call. + getPluginAttachmentRows.mockReturnValue([pluginAttachment1]) + getPluginConfigRows.mockReturnValue([pluginConfig39]) + + await setupPlugins(hub) + const pluginConfig = hub.pluginConfigs.get(39)! + + await pluginConfig.vm?.resolveInternalVm + // async loading of capabilities + expect(setPluginCapabilities.mock.calls.length).toBe(1) + + pluginConfig.updated_at = new Date().toISOString() + // config is changed, but capabilities haven't changed + + await setupPlugins(hub) + const newPluginConfig = hub.pluginConfigs.get(39)! + + await newPluginConfig.vm?.resolveInternalVm + // async loading of capabilities + + expect(newPluginConfig.plugin).not.toBe(pluginConfig.plugin) + expect(setPluginCapabilities.mock.calls.length).toBe(1) + expect(newPluginConfig.plugin!.capabilities).toEqual(pluginConfig.plugin!.capabilities) +}) + +test('plugin lazy loads capabilities', async () => { + getPluginRows.mockReturnValueOnce([ + mockPluginWithArchive(` + function setupPlugin (meta) { meta.global.key = 'value' } + function onEvent (event, meta) { event.properties={"x": 1}; return event } + `), + ]) + getPluginConfigRows.mockReturnValueOnce([pluginConfig39]) + getPluginAttachmentRows.mockReturnValueOnce([pluginAttachment1]) + + await setupPlugins(hub) + const pluginConfig = hub.pluginConfigs.get(39)! + expect(pluginConfig.plugin!.capabilities).toEqual({}) +}) + describe('loadSchedule()', () => { const mockConfig = (tasks: any) => ({ vm: { getTasks: () => Promise.resolve(tasks) } }) - const mockServer = { + const hub = { pluginConfigs: new Map( Object.entries({ 1: {}, @@ -563,12 +732,12 @@ describe('loadSchedule()', () => { } as any it('sets server.pluginSchedule once all plugins are ready', async () => { - const promise = loadSchedule(mockServer) - expect(mockServer.pluginSchedule).toEqual(null) + const promise = loadSchedule(hub) + expect(hub.pluginSchedule).toEqual(null) await promise - expect(mockServer.pluginSchedule).toEqual({ + expect(hub.pluginSchedule).toEqual({ runEveryMinute: ['3'], runEveryHour: ['2'], runEveryDay: [], diff --git a/tests/postgres/vm.lazy.test.ts b/tests/postgres/vm.lazy.test.ts index 7ad072aa0..ca418499d 100644 --- a/tests/postgres/vm.lazy.test.ts +++ b/tests/postgres/vm.lazy.test.ts @@ -5,6 +5,7 @@ import { clearError, processError } from '../../src/utils/db/error' import { status } from '../../src/utils/status' import { LazyPluginVM } from '../../src/worker/vm/lazy' import { createPluginConfigVM } from '../../src/worker/vm/vm' +import { plugin60 } from '../helpers/plugins' import { disablePlugin } from '../helpers/sqlMock' jest.mock('../../src/worker/vm/vm') @@ -16,6 +17,7 @@ const mockConfig = { plugin_id: 60, team_id: 2, id: 39, + plugin: { ...plugin60 }, } describe('LazyPluginVM', () => { diff --git a/tests/postgres/vm.test.ts b/tests/postgres/vm.test.ts index 4b937abfd..02cfee34c 100644 --- a/tests/postgres/vm.test.ts +++ b/tests/postgres/vm.test.ts @@ -62,7 +62,7 @@ test('setupPlugin sync', async () => { ` await resetTestDatabase(indexJs) const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) - const newEvent = await vm.methods.processEvent({ ...defaultEvent }) + const newEvent = await vm.methods.processEvent!({ ...defaultEvent }) expect(newEvent.event).toEqual('haha') }) @@ -79,7 +79,7 @@ test('setupPlugin async', async () => { ` await resetTestDatabase(indexJs) const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) - const newEvent = await vm.methods.processEvent({ ...defaultEvent }) + const newEvent = await vm.methods.processEvent!({ ...defaultEvent }) expect(newEvent.event).toEqual('haha') }) @@ -98,12 +98,12 @@ test('teardownPlugin', async () => { ` await resetTestDatabase(indexJs) const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) - await vm.methods.processEvent({ + await vm.methods.processEvent!({ ...defaultEvent, properties: { haha: 'hoho' }, }) expect(fetch).not.toHaveBeenCalled() - await vm.methods.teardownPlugin() + await vm.methods.teardownPlugin!() expect(fetch).toHaveBeenCalledWith('https://google.com/results.json?query=hoho') }) @@ -123,7 +123,7 @@ test('processEvent', async () => { ...defaultEvent, event: 'original event', } - const newEvent = await vm.methods.processEvent(event) + const newEvent = await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event') expect(newEvent.event).toEqual('changed event') expect(newEvent).toBe(event) @@ -134,7 +134,7 @@ test('processEvent', async () => { event: 'original event', }, ] - const newBatch = await vm.methods.processEventBatch(batch) + const newBatch = await vm.methods.processEventBatch!(batch) expect(batch[0].event).toEqual('changed event') expect(newBatch[0].event).toEqual('changed event') expect(newBatch[0]).toBe(batch[0]) @@ -156,7 +156,7 @@ test('async processEvent', async () => { ...defaultEvent, event: 'original event', } - const newEvent = await vm.methods.processEvent(event) + const newEvent = await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event') expect(newEvent.event).toEqual('changed event') expect(newEvent).toBe(event) @@ -167,7 +167,7 @@ test('async processEvent', async () => { event: 'original event', }, ] - const newBatch = await vm.methods.processEventBatch(batch) + const newBatch = await vm.methods.processEventBatch!(batch) expect(batch[0].event).toEqual('changed event') expect(newBatch[0].event).toEqual('changed event') expect(newBatch[0]).toBe(batch[0]) @@ -191,7 +191,7 @@ test('processEventBatch', async () => { ...defaultEvent, event: 'original event', } - const newEvent = await vm.methods.processEvent(event) + const newEvent = await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event') expect(newEvent.event).toEqual('changed event') expect(newEvent).toBe(event) @@ -202,7 +202,7 @@ test('processEventBatch', async () => { event: 'original event', }, ] - const newBatch = await vm.methods.processEventBatch(batch) + const newBatch = await vm.methods.processEventBatch!(batch) expect(batch[0].event).toEqual('changed event') expect(newBatch[0].event).toEqual('changed event') expect(newBatch[0]).toBe(batch[0]) @@ -226,7 +226,7 @@ test('async processEventBatch', async () => { ...defaultEvent, event: 'original event', } - const newEvent = await vm.methods.processEvent(event) + const newEvent = await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event') expect(newEvent.event).toEqual('changed event') expect(newEvent).toBe(event) @@ -237,7 +237,7 @@ test('async processEventBatch', async () => { event: 'original event', }, ] - const newBatch = await vm.methods.processEventBatch(batch) + const newBatch = await vm.methods.processEventBatch!(batch) expect(batch[0].event).toEqual('changed event') expect(newBatch[0].event).toEqual('changed event') expect(newBatch[0]).toBe(batch[0]) @@ -265,7 +265,7 @@ test('processEvent && processEventBatch', async () => { ...defaultEvent, event: 'original event', } - const newEvent = await vm.methods.processEvent(event) + const newEvent = await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event 1') expect(newEvent.event).toEqual('changed event 1') expect(newEvent).toBe(event) @@ -276,7 +276,7 @@ test('processEvent && processEventBatch', async () => { event: 'original event', }, ] - const newBatch = await vm.methods.processEventBatch(batch) + const newBatch = await vm.methods.processEventBatch!(batch) expect(batch[0].event).toEqual('changed event 2') expect(newBatch[0].event).toEqual('changed event 2') expect(newBatch[0]).toBe(batch[0]) @@ -297,7 +297,7 @@ test('processEvent without returning', async () => { event: 'original event', } - const newEvent = await vm.methods.processEvent(event) + const newEvent = await vm.methods.processEvent!(event) // this will be changed expect(event.event).toEqual('changed event') // but nothing was returned --> bail @@ -320,7 +320,7 @@ test('async processEvent', async () => { ...defaultEvent, event: 'original event', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event') }) @@ -340,7 +340,7 @@ test('module.exports override', async () => { ...defaultEvent, event: 'original event', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event') }) @@ -360,7 +360,7 @@ test('module.exports set', async () => { ...defaultEvent, event: 'original event', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event') }) @@ -379,7 +379,7 @@ test('exports override', async () => { ...defaultEvent, event: 'original event', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event') }) @@ -398,7 +398,7 @@ test('exports set', async () => { ...defaultEvent, event: 'original event', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.event).toEqual('changed event') }) @@ -417,7 +417,7 @@ test('meta.config', async () => { event: 'original event', properties: {}, } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties).toEqual(pluginConfig39.config) }) @@ -442,13 +442,13 @@ test('meta.cache set/get', async () => { properties: {}, } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(1) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(2) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(3) }) @@ -480,13 +480,13 @@ test('meta.storage set/get', async () => { properties: {}, } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(1) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(2) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(3) }) @@ -511,15 +511,15 @@ test('meta.cache expire', async () => { properties: {}, } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(1) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(2) await delay(1200) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(1) }) @@ -543,15 +543,15 @@ test('meta.cache set ttl', async () => { properties: {}, } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(1) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(2) await delay(1200) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(1) }) @@ -574,13 +574,13 @@ test('meta.cache incr', async () => { properties: {}, } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(1) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(2) - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties!['counter']).toEqual(3) }) @@ -600,7 +600,7 @@ test('console.log', async () => { event: 'logged event', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(hub.db.createPluginLogEntry).toHaveBeenCalledWith( pluginConfig39, @@ -626,7 +626,7 @@ test('fetch', async () => { event: 'fetched', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(fetch).toHaveBeenCalledWith('https://google.com/results.json?query=fetched') expect(event.properties).toEqual({ count: 2, query: 'bla', results: [true, true] }) @@ -648,7 +648,7 @@ test('fetch via import', async () => { event: 'fetched', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(fetch).toHaveBeenCalledWith('https://google.com/results.json?query=fetched') expect(event.properties).toEqual({ count: 2, query: 'bla', results: [true, true] }) @@ -669,7 +669,7 @@ test('fetch via require', async () => { event: 'fetched', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(fetch).toHaveBeenCalledWith('https://google.com/results.json?query=fetched') expect(event.properties).toEqual({ count: 2, query: 'bla', results: [true, true] }) @@ -702,7 +702,7 @@ test('attachments', async () => { event: 'attachments', } - await vm.methods.processEvent(event) + await vm.methods.processEvent!(event) expect(event.properties).toEqual(attachments) }) @@ -883,7 +883,7 @@ test('onEvent', async () => { ...defaultEvent, event: 'onEvent', } - await vm.methods.onEvent(event) + await vm.methods.onEvent!(event) expect(fetch).toHaveBeenCalledWith('https://google.com/results.json?query=onEvent') }) @@ -899,6 +899,6 @@ test('onSnapshot', async () => { ...defaultEvent, event: '$snapshot', } - await vm.methods.onSnapshot(event) + await vm.methods.onSnapshot!(event) expect(fetch).toHaveBeenCalledWith('https://google.com/results.json?query=$snapshot') }) diff --git a/tests/postgres/vm.timeout.test.ts b/tests/postgres/vm.timeout.test.ts index 33efe1260..4aa99e111 100644 --- a/tests/postgres/vm.timeout.test.ts +++ b/tests/postgres/vm.timeout.test.ts @@ -41,7 +41,7 @@ describe('vm timeout tests', () => { const date = new Date() let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -62,7 +62,7 @@ describe('vm timeout tests', () => { const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -81,7 +81,7 @@ describe('vm timeout tests', () => { const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -100,7 +100,7 @@ describe('vm timeout tests', () => { const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -120,7 +120,7 @@ describe('vm timeout tests', () => { const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -139,7 +139,7 @@ describe('vm timeout tests', () => { const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -158,7 +158,7 @@ describe('vm timeout tests', () => { const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -178,7 +178,7 @@ describe('vm timeout tests', () => { const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -197,7 +197,7 @@ describe('vm timeout tests', () => { const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -225,7 +225,7 @@ describe('vm timeout tests', () => { const date = new Date() let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -257,7 +257,7 @@ describe('vm timeout tests', () => { const date = new Date() let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message } @@ -278,7 +278,7 @@ describe('vm timeout tests', () => { const vm = await createPluginConfigVM(hub, pluginConfig39, indexJs) let errorMessage = undefined try { - await vm.methods.processEvent({ ...defaultEvent }) + await vm.methods.processEvent!({ ...defaultEvent }) } catch (e) { errorMessage = e.message }