Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Don't run update tests when server may not support update" #412

Merged
merged 2 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions features/update/activities/feature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Feature } from '@temporalio/harness';
import * as wf from '@temporalio/workflow';
import * as assert from 'assert';

const myUpdate = wf.defineUpdate<void>('myUpdate');
const activityCount = 5;
const activityResult = 6;

const activitiesImpl = {
async myActivity(): Promise<number> {
return activityResult;
},
};

const activities = wf.proxyActivities<typeof activitiesImpl>({
startToCloseTimeout: '5s',
});

export const feature = new Feature({
workflow,
activities: activitiesImpl,
checkResult: async (_, handle) => {
await handle.executeUpdate(myUpdate);
const result = await handle.result();
assert.equal(result, activityResult * activityCount);
},
});

export async function workflow(): Promise<number> {
let total = 0;
wf.setHandler(myUpdate, async () => {
const promises = Array.from({ length: activityCount }, activities.myActivity);
const counts = await Promise.all(promises);
total = counts.reduce((a, b) => a + b, 0);
});
await wf.condition(() => total > 0);
return total;
}
45 changes: 45 additions & 0 deletions features/update/async_accepted/feature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as wf from '@temporalio/workflow';
import { Feature } from '@temporalio/harness';
import * as assert from 'assert';
import ms from 'ms';
import { Duration, StringValue } from '@temporalio/common';

const myUpdate = wf.defineUpdate<void, [Duration, boolean]>('myUpdate');
const requestedSleep = '2s';

export const feature = new Feature({
workflow,
checkResult: async (_, handle) => {
const timeToAccept = await time(handle.startUpdate(myUpdate, { args: [requestedSleep, false] }));
const timeToComplete = await time(handle.executeUpdate(myUpdate, { args: [requestedSleep, false] }));
assert.equal(
ms(timeToAccept) < ms(requestedSleep),
true,
`Expected timeToAccept (${timeToAccept}) < requestedSleep (${requestedSleep})`
);
assert.equal(
ms(timeToComplete) >= ms(requestedSleep),
true,
`Expected timeToComplete (${timeToComplete}) >= requestedSleep (${requestedSleep})`
);
await handle.executeUpdate(myUpdate, { args: [0, true] });
await handle.result();
},
});

async function time(promise: Promise<any>): Promise<StringValue> {
const t0 = process.hrtime.bigint();
await promise;
const t1 = process.hrtime.bigint();
const millis = Number((t1 - t0) / BigInt('1000000'));
return `${millis}ms`;
}

export async function workflow(): Promise<void> {
let readyToExitWorkflow = false;
wf.setHandler(myUpdate, async (requestedSleep: Duration, exitWorkflow: boolean) => {
await wf.sleep(requestedSleep);
readyToExitWorkflow = exitWorkflow;
});
await wf.condition(() => readyToExitWorkflow);
}
46 changes: 46 additions & 0 deletions features/update/basic/feature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { WorkflowUpdateFailedError } from '@temporalio/client';
import { Feature } from '@temporalio/harness';
import * as wf from '@temporalio/workflow';
import * as assert from 'assert';

const myUpdate = wf.defineUpdate<string, [string]>('myUpdate');

/**
* A workflow with an update and an update validator. If accepted, the update
* makes a change to workflow state. The workflow does not terminate until such
* a change occurs.
*/
export async function workflow(): Promise<string> {
let state = '';
const validator = (arg: string) => {
if (arg === 'invalid-arg') {
throw new Error('Invalid Update argument');
}
};
const handler = async (arg: string) => {
state = arg;
return 'update-result';
};
wf.setHandler(myUpdate, handler, { validator });
await wf.condition(() => state != '');
return state;
}

export const feature = new Feature({
workflow,
checkResult: async (runner, handle) => {
try {
await handle.executeUpdate(myUpdate, { args: ['invalid-arg'] });
throw 'Expected update to fail';
} catch (err) {
if (!(err instanceof WorkflowUpdateFailedError)) {
throw err;
}
}

const updateResult = await handle.executeUpdate(myUpdate, { args: ['update-arg'] });
assert.equal(updateResult, 'update-result');
const workflowResult = await runner.waitForRunResult(handle);
assert.equal(workflowResult, 'update-arg');
},
});
48 changes: 48 additions & 0 deletions features/update/basic_async/feature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { WorkflowUpdateFailedError } from '@temporalio/client';
import { Feature } from '@temporalio/harness';
import * as wf from '@temporalio/workflow';
import * as assert from 'assert';

const myUpdate = wf.defineUpdate<string, [string]>('myUpdate');

/**
* A workflow with an update and an update validator. If accepted, the update
* makes a change to workflow state. The workflow does not terminate until such
* a change occurs.
*/
export async function workflow(): Promise<string> {
let state = '';
const handler = (arg: string) => {
state = arg;
return 'update-result';
};
const validator = (arg: string) => {
if (arg === 'invalid-arg') {
throw new Error('Invalid Update argument');
}
};
wf.setHandler(myUpdate, handler, { validator });
await wf.condition(() => state != '');
return state;
}

export const feature = new Feature({
workflow,
checkResult: async (runner, handle) => {
const badUpdateHandle = await handle.startUpdate(myUpdate, { args: ['invalid-arg'] });
try {
await badUpdateHandle.result();
throw 'Expected update to fail';
} catch (err) {
if (!(err instanceof WorkflowUpdateFailedError)) {
throw err;
}
}

const updateHandle = await handle.startUpdate(myUpdate, { args: ['update-arg'] });
const updateResult = await updateHandle.result();
assert.equal(updateResult, 'update-result');
const workflowResult = await runner.waitForRunResult(handle);
assert.equal(workflowResult, 'update-arg');
},
});
35 changes: 35 additions & 0 deletions features/update/deduplication/feature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Feature } from '@temporalio/harness';
import * as assert from 'assert';
import * as wf from '@temporalio/workflow';

const increment = wf.defineUpdate<void>('increment');
const getCount = wf.defineQuery<number>('getCount');
const exit = wf.defineUpdate<void>('exit');

export const feature = new Feature({
workflow,
checkResult: async (_, handle) => {
const updateId = 'myUpdateId';
await handle.executeUpdate(increment, { updateId });
assert.equal(await handle.query(getCount), 1);
await handle.executeUpdate(increment, { updateId });
assert.equal(await handle.query(getCount), 1);
await handle.executeUpdate(exit, {});
const count = await handle.result();
assert.equal(count, 1);
},
});

export async function workflow(): Promise<number> {
let count = 0;
let readyToExitWorkflow = false;
wf.setHandler(increment, () => {
count += 1;
});
wf.setHandler(exit, () => {
readyToExitWorkflow = true;
});
wf.setHandler(getCount, () => count);
await wf.condition(() => readyToExitWorkflow);
return count;
}
Loading