@@ -10,10 +10,16 @@ import {
10
10
ScheduleHandle ,
11
11
ScheduleSummary ,
12
12
ScheduleUpdateOptions ,
13
+ ScheduleDescription ,
13
14
} from '@temporalio/client' ;
14
15
import { msToNumber } from '@temporalio/common/lib/time' ;
15
- import { SearchAttributes , SearchAttributeType , TypedSearchAttributes } from '@temporalio/common' ;
16
- import { registerDefaultCustomSearchAttributes , RUN_INTEGRATION_TESTS } from './helpers' ;
16
+ import {
17
+ SearchAttributeType ,
18
+ SearchAttributes ,
19
+ TypedSearchAttributes ,
20
+ defineSearchAttributeKey ,
21
+ } from '@temporalio/common' ;
22
+ import { registerDefaultCustomSearchAttributes , RUN_INTEGRATION_TESTS , waitUntil } from './helpers' ;
17
23
18
24
export interface Context {
19
25
client : Client ;
@@ -758,4 +764,128 @@ if (RUN_INTEGRATION_TESTS) {
758
764
await handle . delete ( ) ;
759
765
}
760
766
} ) ;
767
+
768
+ test . serial ( 'Can update search attributes of a schedule' , async ( t ) => {
769
+ const { client } = t . context ;
770
+ const scheduleId = `can-update-search-attributes-of-schedule-${ randomUUID ( ) } ` ;
771
+
772
+ // Helper to wait for search attribute changes to propagate.
773
+ const waitForAttributeChange = async (
774
+ handle : ScheduleHandle ,
775
+ attributeName : string ,
776
+ shouldExist : boolean
777
+ ) : Promise < ScheduleDescription > => {
778
+ await waitUntil ( async ( ) => {
779
+ const desc = await handle . describe ( ) ;
780
+ const exists =
781
+ desc . typedSearchAttributes . getAll ( ) . find ( ( pair ) => pair . key . name === attributeName ) !== undefined ;
782
+ return exists === shouldExist ;
783
+ } , 300 ) ;
784
+ return await handle . describe ( ) ;
785
+ } ;
786
+
787
+ // Create a schedule with search attributes.
788
+ const handle = await client . schedule . create ( {
789
+ scheduleId,
790
+ spec : {
791
+ calendars : [ { hour : { start : 2 , end : 7 , step : 1 } } ] ,
792
+ } ,
793
+ action : {
794
+ type : 'startWorkflow' ,
795
+ workflowType : dummyWorkflow ,
796
+ taskQueue,
797
+ } ,
798
+ searchAttributes : {
799
+ CustomKeywordField : [ 'keyword-one' ] ,
800
+ } ,
801
+ typedSearchAttributes : [ { key : defineSearchAttributeKey ( 'CustomIntField' , SearchAttributeType . INT ) , value : 1 } ] ,
802
+ } ) ;
803
+
804
+ // Check the search attributes are part of the schedule description.
805
+ const desc = await handle . describe ( ) ;
806
+ // eslint-disable-next-line deprecation/deprecation
807
+ t . deepEqual ( desc . searchAttributes , {
808
+ CustomKeywordField : [ 'keyword-one' ] ,
809
+ CustomIntField : [ 1 ] ,
810
+ } ) ;
811
+ t . deepEqual (
812
+ desc . typedSearchAttributes ,
813
+ new TypedSearchAttributes ( [
814
+ { key : defineSearchAttributeKey ( 'CustomIntField' , SearchAttributeType . INT ) , value : 1 } ,
815
+ { key : defineSearchAttributeKey ( 'CustomKeywordField' , SearchAttributeType . KEYWORD ) , value : 'keyword-one' } ,
816
+ ] )
817
+ ) ;
818
+
819
+ // Perform a series of updates to schedule's search attributes.
820
+ try {
821
+ // Update existing search attributes, add new ones.
822
+ await handle . update ( ( desc ) => ( {
823
+ ...desc ,
824
+ searchAttributes : {
825
+ CustomKeywordField : [ 'keyword-two' ] ,
826
+ // Add a new search attribute.
827
+ CustomDoubleField : [ 1.5 ] ,
828
+ } ,
829
+ typedSearchAttributes : [
830
+ { key : defineSearchAttributeKey ( 'CustomIntField' , SearchAttributeType . INT ) , value : 2 } ,
831
+ // Add a new typed search attribute.
832
+ { key : defineSearchAttributeKey ( 'CustomTextField' , SearchAttributeType . TEXT ) , value : 'new-text' } ,
833
+ ] ,
834
+ } ) ) ;
835
+
836
+ let desc = await waitForAttributeChange ( handle , 'CustomTextField' , true ) ;
837
+ // eslint-disable-next-line deprecation/deprecation
838
+ t . deepEqual ( desc . searchAttributes , {
839
+ CustomKeywordField : [ 'keyword-two' ] ,
840
+ CustomIntField : [ 2 ] ,
841
+ CustomDoubleField : [ 1.5 ] ,
842
+ CustomTextField : [ 'new-text' ] ,
843
+ } ) ;
844
+ t . deepEqual (
845
+ desc . typedSearchAttributes ,
846
+ new TypedSearchAttributes ( [
847
+ { key : defineSearchAttributeKey ( 'CustomIntField' , SearchAttributeType . INT ) , value : 2 } ,
848
+ { key : defineSearchAttributeKey ( 'CustomKeywordField' , SearchAttributeType . KEYWORD ) , value : 'keyword-two' } ,
849
+ { key : defineSearchAttributeKey ( 'CustomTextField' , SearchAttributeType . TEXT ) , value : 'new-text' } ,
850
+ { key : defineSearchAttributeKey ( 'CustomDoubleField' , SearchAttributeType . DOUBLE ) , value : 1.5 } ,
851
+ ] )
852
+ ) ;
853
+
854
+ // Update and remove some search attributes. We remove a search attribute by omitting an existing key from the update.
855
+ await handle . update ( ( desc ) => ( {
856
+ ...desc ,
857
+ searchAttributes : {
858
+ CustomKeywordField : [ 'keyword-three' ] ,
859
+ } ,
860
+ typedSearchAttributes : [ { key : defineSearchAttributeKey ( 'CustomIntField' , SearchAttributeType . INT ) , value : 3 } ] ,
861
+ } ) ) ;
862
+
863
+ desc = await waitForAttributeChange ( handle , 'CustomTextField' , false ) ;
864
+ // eslint-disable-next-line deprecation/deprecation
865
+ t . deepEqual ( desc . searchAttributes , {
866
+ CustomKeywordField : [ 'keyword-three' ] ,
867
+ CustomIntField : [ 3 ] ,
868
+ } ) ;
869
+ t . deepEqual (
870
+ desc . typedSearchAttributes ,
871
+ new TypedSearchAttributes ( [
872
+ { key : defineSearchAttributeKey ( 'CustomIntField' , SearchAttributeType . INT ) , value : 3 } ,
873
+ { key : defineSearchAttributeKey ( 'CustomKeywordField' , SearchAttributeType . KEYWORD ) , value : 'keyword-three' } ,
874
+ ] )
875
+ ) ;
876
+
877
+ // Remove all search attributes.
878
+ await handle . update ( ( desc ) => ( {
879
+ ...desc ,
880
+ searchAttributes : { } ,
881
+ typedSearchAttributes : [ ] ,
882
+ } ) ) ;
883
+
884
+ desc = await waitForAttributeChange ( handle , 'CustomIntField' , false ) ;
885
+ t . deepEqual ( desc . searchAttributes , { } ) ; // eslint-disable-line deprecation/deprecation
886
+ t . deepEqual ( desc . typedSearchAttributes , new TypedSearchAttributes ( [ ] ) ) ;
887
+ } finally {
888
+ await handle . delete ( ) ;
889
+ }
890
+ } ) ;
761
891
}
0 commit comments