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

Typed search attributes #1612

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
11 changes: 4 additions & 7 deletions packages/client/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ServiceError as GrpcServiceError, status as grpcStatus } from '@grpc/grpc-js';
import {
decodeSearchAttributes,
decodeTypedSearchAttributes,
LoadedDataConverter,
mapFromPayloads,
NamespaceNotFoundError,
searchAttributePayloadConverter,
SearchAttributes,
} from '@temporalio/common';
import { Replace } from '@temporalio/common/lib/type-helpers';
import { optionalTsToDate, requiredTsToDate } from '@temporalio/common/lib/time';
Expand Down Expand Up @@ -71,11 +71,8 @@ export async function executionInfoFromRaw<T>(
executionTime: optionalTsToDate(raw.executionTime),
closeTime: optionalTsToDate(raw.closeTime),
memo: await decodeMapFromPayloads(dataConverter, raw.memo?.fields),
searchAttributes: Object.fromEntries(
Object.entries(
mapFromPayloads(searchAttributePayloadConverter, raw.searchAttributes?.indexedFields ?? {}) as SearchAttributes
).filter(([_, v]) => v && v.length > 0) // Filter out empty arrays returned by pre 1.18 servers
),
searchAttributes: decodeSearchAttributes(raw.searchAttributes?.indexedFields),
typedSearchAttributes: decodeTypedSearchAttributes(raw.searchAttributes?.indexedFields),
parentExecution: raw.parentExecution
? {
workflowId: raw.parentExecution.workflowId!,
Expand Down
25 changes: 16 additions & 9 deletions packages/client/src/schedule-client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { status as grpcStatus } from '@grpc/grpc-js';
import { v4 as uuid4 } from 'uuid';
import { mapToPayloads, searchAttributePayloadConverter, Workflow } from '@temporalio/common';
import {
decodeSearchAttributes,
decodeTypedSearchAttributes,
encodeUnifiedSearchAttributes,
Workflow,
} from '@temporalio/common';
import { composeInterceptors, Headers } from '@temporalio/common/lib/interceptors';
import {
encodeMapToPayloads,
Expand Down Expand Up @@ -39,7 +44,6 @@
decodeScheduleRecentActions,
decodeScheduleRunningActions,
decodeScheduleSpec,
decodeSearchAttributes,
encodeScheduleAction,
encodeSchedulePolicies,
encodeScheduleSpec,
Expand Down Expand Up @@ -238,11 +242,12 @@
state: encodeScheduleState(opts.state),
},
memo: opts.memo ? { fields: await encodeMapToPayloads(this.dataConverter, opts.memo) } : undefined,
searchAttributes: opts.searchAttributes
? {
indexedFields: mapToPayloads(searchAttributePayloadConverter, opts.searchAttributes),
}
: undefined,
searchAttributes:
opts.searchAttributes || opts.typedSearchAttributes

Check warning on line 246 in packages/client/src/schedule-client.ts

View workflow job for this annotation

GitHub Actions / Lint and Prune / Lint and Prune

'searchAttributes' is deprecated. Use {@link typedSearchAttributes } instead
? {
indexedFields: encodeUnifiedSearchAttributes(opts.searchAttributes, opts.typedSearchAttributes),

Check warning on line 248 in packages/client/src/schedule-client.ts

View workflow job for this annotation

GitHub Actions / Lint and Prune / Lint and Prune

'searchAttributes' is deprecated. Use {@link typedSearchAttributes } instead
}
: undefined,
initialPatch: {
triggerImmediately: opts.state?.triggerImmediately
? { overlapPolicy: temporal.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_ALLOW_ALL }
Expand Down Expand Up @@ -388,7 +393,8 @@
workflowType: raw.info.workflowType.name,
},
memo: await decodeMapFromPayloads(this.dataConverter, raw.memo?.fields),
searchAttributes: decodeSearchAttributes(raw.searchAttributes),
searchAttributes: decodeSearchAttributes(raw.searchAttributes?.indexedFields),
typedSearchAttributes: decodeTypedSearchAttributes(raw.searchAttributes?.indexedFields),
state: {
paused: raw.info?.paused === true,
note: raw.info?.notes ?? undefined,
Expand Down Expand Up @@ -425,7 +431,8 @@
spec: decodeScheduleSpec(raw.schedule.spec),
action: await decodeScheduleAction(this.client.dataConverter, raw.schedule.action),
memo: await decodeMapFromPayloads(this.client.dataConverter, raw.memo?.fields),
searchAttributes: decodeSearchAttributes(raw.searchAttributes),
searchAttributes: decodeSearchAttributes(raw.searchAttributes?.indexedFields),
typedSearchAttributes: decodeTypedSearchAttributes(raw.searchAttributes?.indexedFields),
policies: {
// 'overlap' should never be missing on describe, as the server will replace UNSPECIFIED by an actual value
overlap: decodeScheduleOverlapPolicy(raw.schedule.policies?.overlapPolicy) ?? ScheduleOverlapPolicy.SKIP,
Expand Down
39 changes: 11 additions & 28 deletions packages/client/src/schedule-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import Long from 'long'; // eslint-disable-line import/no-named-as-default
import {
compileRetryPolicy,
decodeSearchAttributes,
decodeTypedSearchAttributes,
decompileRetryPolicy,
encodeUnifiedSearchAttributes,
extractWorkflowType,
LoadedDataConverter,
mapFromPayloads,
mapToPayloads,
searchAttributePayloadConverter,
SearchAttributes,
} from '@temporalio/common';
import { Headers } from '@temporalio/common/lib/interceptors';
import {
Expand Down Expand Up @@ -260,11 +259,12 @@
workflowTaskTimeout: msOptionalToTs(action.workflowTaskTimeout),
retryPolicy: action.retry ? compileRetryPolicy(action.retry) : undefined,
memo: action.memo ? { fields: await encodeMapToPayloads(dataConverter, action.memo) } : undefined,
searchAttributes: action.searchAttributes
? {
indexedFields: mapToPayloads(searchAttributePayloadConverter, action.searchAttributes),
}
: undefined,
searchAttributes:
action.searchAttributes || action.typedSearchAttributes

Check warning on line 263 in packages/client/src/schedule-helpers.ts

View workflow job for this annotation

GitHub Actions / Lint and Prune / Lint and Prune

'searchAttributes' is deprecated. Use {@link typedSearchAttributes } instead
? {
indexedFields: encodeUnifiedSearchAttributes(action.searchAttributes, action.typedSearchAttributes),

Check warning on line 265 in packages/client/src/schedule-helpers.ts

View workflow job for this annotation

GitHub Actions / Lint and Prune / Lint and Prune

'searchAttributes' is deprecated. Use {@link typedSearchAttributes } instead
}
: undefined,
header: { fields: headers },
},
};
Expand Down Expand Up @@ -326,14 +326,8 @@
args: await decodeArrayFromPayloads(dataConverter, pb.startWorkflow.input?.payloads),
memo: await decodeMapFromPayloads(dataConverter, pb.startWorkflow.memo?.fields),
retry: decompileRetryPolicy(pb.startWorkflow.retryPolicy),
searchAttributes: Object.fromEntries(
Object.entries(
mapFromPayloads(
searchAttributePayloadConverter,
pb.startWorkflow.searchAttributes?.indexedFields ?? {}
) as SearchAttributes
)
),
searchAttributes: decodeSearchAttributes(pb.startWorkflow.searchAttributes?.indexedFields),
typedSearchAttributes: decodeTypedSearchAttributes(pb.startWorkflow.searchAttributes?.indexedFields),
workflowExecutionTimeout: optionalTsToMs(pb.startWorkflow.workflowExecutionTimeout),
workflowRunTimeout: optionalTsToMs(pb.startWorkflow.workflowRunTimeout),
workflowTaskTimeout: optionalTsToMs(pb.startWorkflow.workflowTaskTimeout),
Expand All @@ -342,17 +336,6 @@
throw new TypeError('Unsupported schedule action');
}

export function decodeSearchAttributes(
pb: temporal.api.common.v1.ISearchAttributes | undefined | null
): SearchAttributes {
if (!pb?.indexedFields) return {};
return Object.fromEntries(
Object.entries(mapFromPayloads(searchAttributePayloadConverter, pb.indexedFields) as SearchAttributes).filter(
([_, v]) => v && v.length > 0
) // Filter out empty arrays returned by pre 1.18 servers
);
}

export function decodeScheduleRunningActions(
pb?: temporal.api.common.v1.IWorkflowExecution[] | null
): ScheduleExecutionStartWorkflowActionResult[] {
Expand Down
54 changes: 48 additions & 6 deletions packages/client/src/schedule-types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { checkExtends, Replace } from '@temporalio/common/lib/type-helpers';
import { Duration, SearchAttributes, Workflow } from '@temporalio/common';
import {
Duration,
SearchAttributes,
Workflow,
TypedSearchAttributePair,
TypedSearchAttributes,
} from '@temporalio/common';
import { makeProtoEnumConverters } from '@temporalio/common/lib/internal-workflow';
import type { temporal } from '@temporalio/proto';
import { WorkflowStartOptions } from './workflow-options';
Expand Down Expand Up @@ -70,9 +76,22 @@ export interface ScheduleOptions<A extends ScheduleOptionsAction = ScheduleOptio
* https://docs.temporal.io/docs/typescript/search-attributes
*
* Values are always converted using {@link JsonPayloadConverter}, even when a custom Data Converter is provided.
*
* @deprecated Use {@link typedSearchAttributes} instead.
*/
searchAttributes?: SearchAttributes;

/**
* Additional indexed information attached to the Schedule. More info:
* https://docs.temporal.io/docs/typescript/search-attributes
*
* Values are always converted using {@link JsonPayloadConverter}, even when a custom Data Converter is provided.
*
* If both {@link searchAttributes} and {@link typedSearchAttributes} are provided, conflicting keys will be overwritten
* by {@link typedSearchAttributes}.
*/
typedSearchAttributes?: TypedSearchAttributePair[] | TypedSearchAttributes;

/**
* The initial state of the schedule, right after creation or update.
*/
Expand Down Expand Up @@ -128,8 +147,9 @@ export type CompiledScheduleOptions = Replace<
/**
* The specification of an updated Schedule, as expected by {@link ScheduleHandle.update}.
*/
// TODO(thomas): support search attributes on update (ts issue #1475)
export type ScheduleUpdateOptions<A extends ScheduleOptionsAction = ScheduleOptionsAction> = Replace<
Omit<ScheduleOptions, 'scheduleId' | 'memo' | 'searchAttributes'>,
Omit<ScheduleOptions, 'scheduleId' | 'memo' | 'searchAttributes' | 'typedSearchAttributes'>,
{
action: A;
state: Omit<ScheduleOptions['state'], 'triggerImmediately' | 'backfill'>;
Expand Down Expand Up @@ -172,13 +192,23 @@ export interface ScheduleSummary {
memo?: Record<string, unknown>;

/**
* Additional indexed information attached to the Schedule.
* More info: https://docs.temporal.io/docs/typescript/search-attributes
* Additional indexed information attached to the Schedule. More info:
* https://docs.temporal.io/docs/typescript/search-attributes
*
* Values are always converted using {@link JsonPayloadConverter}, even when a custom Data Converter is provided.
*
* @deprecated Use {@link typedSearchAttributes} instead.
*/
searchAttributes?: SearchAttributes;

/**
* Additional indexed information attached to the Schedule. More info:
* https://docs.temporal.io/docs/typescript/search-attributes
*
* Values are always converted using {@link JsonPayloadConverter}, even when a custom Data Converter is provided.
*/
typedSearchAttributes?: TypedSearchAttributes;

state: {
/**
* Whether Schedule is currently paused.
Expand Down Expand Up @@ -284,13 +314,23 @@ export type ScheduleDescription = {
memo?: Record<string, unknown>;

/**
* Additional indexed information attached to the Schedule.
* More info: https://docs.temporal.io/docs/typescript/search-attributes
* Additional indexed information attached to the Schedule. More info:
* https://docs.temporal.io/docs/typescript/search-attributes
*
* Values are always converted using {@link JsonPayloadConverter}, even when a custom Data Converter is provided.
*
* @deprecated Use {@link typedSearchAttributes} instead.
*/
searchAttributes: SearchAttributes;

/**
* Additional indexed information attached to the Schedule. More info:
* https://docs.temporal.io/docs/typescript/search-attributes
*
* Values are always converted using {@link JsonPayloadConverter}, even when a custom Data Converter is provided.
*/
typedSearchAttributes: TypedSearchAttributes;

state: {
/**
* Whether Schedule is currently paused.
Expand Down Expand Up @@ -745,6 +785,7 @@ export type ScheduleOptionsStartWorkflowAction<W extends Workflow> = {
| 'args'
| 'memo'
| 'searchAttributes'
| 'typedSearchAttributes'
| 'retry'
| 'workflowExecutionTimeout'
| 'workflowRunTimeout'
Expand Down Expand Up @@ -776,6 +817,7 @@ export type ScheduleDescriptionStartWorkflowAction = ScheduleSummaryStartWorkflo
| 'args'
| 'memo'
| 'searchAttributes'
| 'typedSearchAttributes'
| 'retry'
| 'workflowExecutionTimeout'
| 'workflowRunTimeout'
Expand Down
4 changes: 3 additions & 1 deletion packages/client/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type * as grpc from '@grpc/grpc-js';
import type { SearchAttributes, SearchAttributeValue } from '@temporalio/common';
import type { SearchAttributes, SearchAttributeValue, TypedSearchAttributes } from '@temporalio/common';
import { makeProtoEnumConverters } from '@temporalio/common/lib/internal-workflow';
import * as proto from '@temporalio/proto';
import { Replace } from '@temporalio/common/lib/type-helpers';
Expand Down Expand Up @@ -47,7 +47,9 @@ export interface WorkflowExecutionInfo {
executionTime?: Date;
closeTime?: Date;
memo?: Record<string, unknown>;
/** @deprecated Use {@link typedSearchAttributes} instead. */
searchAttributes: SearchAttributes;
typedSearchAttributes: TypedSearchAttributes;
parentExecution?: Required<proto.temporal.api.common.v1.IWorkflowExecution>;
raw: RawWorkflowExecutionInfo;
}
Expand Down
26 changes: 14 additions & 12 deletions packages/client/src/workflow-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
BaseWorkflowHandle,
CancelledFailure,
compileRetryPolicy,
mapToPayloads,
HistoryAndWorkflowId,
QueryDefinition,
RetryState,
searchAttributePayloadConverter,
SignalDefinition,
UpdateDefinition,
TerminatedFailure,
Expand All @@ -24,6 +22,7 @@
decodeRetryState,
encodeWorkflowIdConflictPolicy,
WorkflowIdConflictPolicy,
encodeUnifiedSearchAttributes,
} from '@temporalio/common';
import { composeInterceptors } from '@temporalio/common/lib/interceptors';
import { History } from '@temporalio/common/lib/proto-utils';
Expand Down Expand Up @@ -1218,11 +1217,12 @@
workflowStartDelay: options.startDelay,
retryPolicy: options.retry ? compileRetryPolicy(options.retry) : undefined,
memo: options.memo ? { fields: await encodeMapToPayloads(this.dataConverter, options.memo) } : undefined,
searchAttributes: options.searchAttributes
? {
indexedFields: mapToPayloads(searchAttributePayloadConverter, options.searchAttributes),
}
: undefined,
searchAttributes:
options.searchAttributes || options.typedSearchAttributes

Check warning on line 1221 in packages/client/src/workflow-client.ts

View workflow job for this annotation

GitHub Actions / Lint and Prune / Lint and Prune

'searchAttributes' is deprecated. Use {@link typedSearchAttributes } instead
? {
indexedFields: encodeUnifiedSearchAttributes(options.searchAttributes, options.typedSearchAttributes),

Check warning on line 1223 in packages/client/src/workflow-client.ts

View workflow job for this annotation

GitHub Actions / Lint and Prune / Lint and Prune

'searchAttributes' is deprecated. Use {@link typedSearchAttributes } instead
}
: undefined,
cronSchedule: options.cronSchedule,
header: { fields: headers },
};
Expand Down Expand Up @@ -1265,6 +1265,7 @@
protected async createStartWorkflowRequest(input: WorkflowStartInput): Promise<StartWorkflowExecutionRequest> {
const { options: opts, workflowType, headers } = input;
const { identity, namespace } = this.options;

return {
namespace,
identity,
Expand All @@ -1284,11 +1285,12 @@
workflowStartDelay: opts.startDelay,
retryPolicy: opts.retry ? compileRetryPolicy(opts.retry) : undefined,
memo: opts.memo ? { fields: await encodeMapToPayloads(this.dataConverter, opts.memo) } : undefined,
searchAttributes: opts.searchAttributes
? {
indexedFields: mapToPayloads(searchAttributePayloadConverter, opts.searchAttributes),
}
: undefined,
searchAttributes:
opts.searchAttributes || opts.typedSearchAttributes

Check warning on line 1289 in packages/client/src/workflow-client.ts

View workflow job for this annotation

GitHub Actions / Lint and Prune / Lint and Prune

'searchAttributes' is deprecated. Use {@link typedSearchAttributes } instead
? {
indexedFields: encodeUnifiedSearchAttributes(opts.searchAttributes, opts.typedSearchAttributes),

Check warning on line 1291 in packages/client/src/workflow-client.ts

View workflow job for this annotation

GitHub Actions / Lint and Prune / Lint and Prune

'searchAttributes' is deprecated. Use {@link typedSearchAttributes } instead
}
: undefined,
cronSchedule: opts.cronSchedule,
header: { fields: headers },
};
Expand Down
Loading
Loading