@@ -18,6 +18,7 @@ import (
18
18
"github.com/coder/coder/v2/coderd/coderdtest"
19
19
"github.com/coder/coder/v2/coderd/database"
20
20
"github.com/coder/coder/v2/coderd/database/dbauthz"
21
+ "github.com/coder/coder/v2/coderd/database/dbtestutil"
21
22
"github.com/coder/coder/v2/coderd/notifications"
22
23
"github.com/coder/coder/v2/coderd/notifications/notificationstest"
23
24
"github.com/coder/coder/v2/coderd/schedule"
@@ -72,6 +73,76 @@ func TestExecutorAutostartOK(t *testing.T) {
72
73
require .Equal (t , template .AutostartRequirement .DaysOfWeek , []string {"monday" , "tuesday" , "wednesday" , "thursday" , "friday" , "saturday" , "sunday" })
73
74
}
74
75
76
+ func TestMultipleLifecycleExecutors (t * testing.T ) {
77
+ t .Parallel ()
78
+
79
+ db , ps := dbtestutil .NewDB (t )
80
+
81
+ var (
82
+ sched = mustSchedule (t , "CRON_TZ=UTC 0 * * * *" )
83
+ // Create our first client
84
+ tickCh = make (chan time.Time , 2 )
85
+ statsChA = make (chan autobuild.Stats )
86
+ clientA = coderdtest .New (t , & coderdtest.Options {
87
+ IncludeProvisionerDaemon : true ,
88
+ AutobuildTicker : tickCh ,
89
+ AutobuildStats : statsChA ,
90
+ Database : db ,
91
+ Pubsub : ps ,
92
+ })
93
+ // ... And then our second client
94
+ statsChB = make (chan autobuild.Stats )
95
+ _ = coderdtest .New (t , & coderdtest.Options {
96
+ IncludeProvisionerDaemon : true ,
97
+ AutobuildTicker : tickCh ,
98
+ AutobuildStats : statsChB ,
99
+ Database : db ,
100
+ Pubsub : ps ,
101
+ })
102
+ // Now create a workspace (we can use either client, it doesn't matter)
103
+ workspace = mustProvisionWorkspace (t , clientA , func (cwr * codersdk.CreateWorkspaceRequest ) {
104
+ cwr .AutostartSchedule = ptr .Ref (sched .String ())
105
+ })
106
+ )
107
+
108
+ // Have the workspace stopped so we can perform an autostart
109
+ workspace = coderdtest .MustTransitionWorkspace (t , clientA , workspace .ID , database .WorkspaceTransitionStart , database .WorkspaceTransitionStop )
110
+
111
+ // Get both clients to perform a lifecycle execution tick
112
+ next := sched .Next (workspace .LatestBuild .CreatedAt )
113
+
114
+ startCh := make (chan struct {})
115
+ go func () {
116
+ <- startCh
117
+ tickCh <- next
118
+ }()
119
+ go func () {
120
+ <- startCh
121
+ tickCh <- next
122
+ }()
123
+ close (startCh )
124
+
125
+ // Now we want to check the stats for both clients
126
+ statsA := <- statsChA
127
+ statsB := <- statsChB
128
+
129
+ // We expect there to be no errors
130
+ assert .Len (t , statsA .Errors , 0 )
131
+ assert .Len (t , statsB .Errors , 0 )
132
+
133
+ // We also expect there to have been only one transition
134
+ require .Equal (t , 1 , len (statsA .Transitions )+ len (statsB .Transitions ))
135
+
136
+ stats := statsA
137
+ if len (statsB .Transitions ) == 1 {
138
+ stats = statsB
139
+ }
140
+
141
+ // And we expect this transition to have been a start transition
142
+ assert .Contains (t , stats .Transitions , workspace .ID )
143
+ assert .Equal (t , database .WorkspaceTransitionStart , stats .Transitions [workspace .ID ])
144
+ }
145
+
75
146
func TestExecutorAutostartTemplateUpdated (t * testing.T ) {
76
147
t .Parallel ()
77
148
0 commit comments