@@ -43,9 +43,11 @@ import (
4343 "go.temporal.io/api/workflowservice/v1"
4444
4545 "go.temporal.io/server/api/adminservice/v1"
46+ "go.temporal.io/server/common"
4647 "go.temporal.io/server/common/backoff"
4748 "go.temporal.io/server/common/dynamicconfig"
4849 "go.temporal.io/server/common/log"
50+ "go.temporal.io/server/common/persistence"
4951 "go.temporal.io/server/common/persistence/sql/sqlplugin/mysql"
5052 "go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql"
5153 "go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite"
@@ -190,24 +192,28 @@ func (s *namespaceTestSuite) Test_NamespaceDelete_WithWorkflows() {
190192 nsID := descResp .GetNamespaceInfo ().GetId ()
191193
192194 // Start few workflow executions.
195+ var executions []* commonpb.WorkflowExecution
193196 for i := 0 ; i < 100 ; i ++ {
194- _ , err = s .frontendClient .StartWorkflowExecution (ctx , & workflowservice.StartWorkflowExecutionRequest {
197+ wid := "wf_id_" + strconv .Itoa (i )
198+ resp , err := s .frontendClient .StartWorkflowExecution (ctx , & workflowservice.StartWorkflowExecutionRequest {
195199 RequestId : uuid .New (),
196200 Namespace : "ns_name_los_angeles" ,
197- WorkflowId : "wf_id_" + strconv . Itoa ( i ) ,
201+ WorkflowId : wid ,
198202 WorkflowType : & commonpb.WorkflowType {Name : "workflowTypeName" },
199203 TaskQueue : & taskqueuepb.TaskQueue {Name : "taskQueueName" },
200204 })
201205 s .NoError (err )
206+ executions = append (executions , & commonpb.WorkflowExecution {
207+ WorkflowId : wid ,
208+ RunId : resp .GetRunId (),
209+ })
202210 }
203211
204212 // Terminate some workflow executions.
205- for i := 0 ; i < 30 ; i ++ {
213+ for _ , execution := range executions [: 30 ] {
206214 _ , err = s .frontendClient .TerminateWorkflowExecution (ctx , & workflowservice.TerminateWorkflowExecutionRequest {
207- Namespace : "ns_name_los_angeles" ,
208- WorkflowExecution : & commonpb.WorkflowExecution {
209- WorkflowId : "wf_id_" + strconv .Itoa (i ),
210- },
215+ Namespace : "ns_name_los_angeles" ,
216+ WorkflowExecution : execution ,
211217 })
212218 s .NoError (err )
213219 }
@@ -224,37 +230,123 @@ func (s *namespaceTestSuite) Test_NamespaceDelete_WithWorkflows() {
224230 s .NoError (err )
225231 s .Equal (enumspb .NAMESPACE_STATE_DELETED , descResp2 .GetNamespaceInfo ().GetState ())
226232
227- namespaceExistsOp := func () error {
233+ s . Eventually ( func () bool {
228234 _ , err := s .frontendClient .DescribeNamespace (ctx , & workflowservice.DescribeNamespaceRequest {
229235 Id : nsID ,
230236 })
231237 var notFound * serviceerror.NamespaceNotFound
232- if errors .As (err , & notFound ) {
233- _ , err0 := s .frontendClient .DescribeWorkflowExecution (ctx , & workflowservice.DescribeWorkflowExecutionRequest {
234- Namespace : "ns_name_los_angeles" ,
235- Execution : & commonpb.WorkflowExecution {
236- WorkflowId : "wf_id_0" ,
237- },
238- })
239- _ , err99 := s .frontendClient .DescribeWorkflowExecution (ctx , & workflowservice.DescribeWorkflowExecutionRequest {
238+ if ! errors .As (err , & notFound ) {
239+ return false // namespace still exists
240+ }
241+
242+ for _ , execution := range executions {
243+ _ , err = s .frontendClient .DescribeWorkflowExecution (ctx , & workflowservice.DescribeWorkflowExecutionRequest {
240244 Namespace : "ns_name_los_angeles" ,
241245 Execution : & commonpb.WorkflowExecution {
242- WorkflowId : "wf_id_99" ,
246+ WorkflowId : execution . GetWorkflowId () ,
243247 },
244248 })
245- if errors .As (err0 , & notFound ) && errors . As ( err99 , & notFound ) {
246- return nil
249+ if ! errors .As (err , & notFound ) {
250+ return false // should never happen
247251 }
248252 }
249- return errors .New ("namespace still exists" )
253+ return true
254+ }, 20 * time .Second , time .Second )
255+ }
256+
257+ func (s * namespaceTestSuite ) Test_NamespaceDelete_WithMissingWorkflows () {
258+ ctx , cancel := rpc .NewContextWithTimeoutAndVersionHeaders (10000 * time .Second )
259+ defer cancel ()
260+
261+ retention := 24 * time .Hour
262+ _ , err := s .frontendClient .RegisterNamespace (ctx , & workflowservice.RegisterNamespaceRequest {
263+ Namespace : "ns_name_los_angeles" ,
264+ Description : "Namespace to delete" ,
265+ WorkflowExecutionRetentionPeriod : & retention ,
266+ HistoryArchivalState : enumspb .ARCHIVAL_STATE_DISABLED ,
267+ VisibilityArchivalState : enumspb .ARCHIVAL_STATE_DISABLED ,
268+ })
269+ s .NoError (err )
270+ // DescribeNamespace reads directly from database but namespace validator uses cache.
271+ s .cluster .RefreshNamespaceCache ()
272+
273+ descResp , err := s .frontendClient .DescribeNamespace (ctx , & workflowservice.DescribeNamespaceRequest {
274+ Namespace : "ns_name_los_angeles" ,
275+ })
276+ s .NoError (err )
277+ nsID := descResp .GetNamespaceInfo ().GetId ()
278+
279+ // Start few workflow executions.
280+
281+ var executions []* commonpb.WorkflowExecution
282+ for i := 0 ; i < 10 ; i ++ {
283+ wid := "wf_id_" + strconv .Itoa (i )
284+ resp , err := s .frontendClient .StartWorkflowExecution (ctx , & workflowservice.StartWorkflowExecutionRequest {
285+ RequestId : uuid .New (),
286+ Namespace : "ns_name_los_angeles" ,
287+ WorkflowId : wid ,
288+ WorkflowType : & commonpb.WorkflowType {Name : "workflowTypeName" },
289+ TaskQueue : & taskqueuepb.TaskQueue {Name : "taskQueueName" },
290+ })
291+ s .NoError (err )
292+ executions = append (executions , & commonpb.WorkflowExecution {
293+ WorkflowId : wid ,
294+ RunId : resp .GetRunId (),
295+ })
250296 }
251297
252- namespaceExistsPolicy := backoff .NewExponentialRetryPolicy (time .Second ).
253- WithBackoffCoefficient (1 ).
254- WithExpirationInterval (30 * time .Second )
298+ // Delete some workflow executions from DB but not from visibility.
299+ // Every subsequent delete (from deleteexecutions.Workflow) from ES will take at least 1s due to bulk processor.
300+ for _ , execution := range executions [0 :5 ] {
301+ shardID := common .WorkflowIDToHistoryShard (
302+ nsID ,
303+ execution .GetWorkflowId (),
304+ s .clusterConfig .HistoryConfig .NumHistoryShards ,
305+ )
306+
307+ err = s .cluster .GetExecutionManager ().DeleteWorkflowExecution (ctx , & persistence.DeleteWorkflowExecutionRequest {
308+ ShardID : shardID ,
309+ NamespaceID : nsID ,
310+ WorkflowID : execution .GetWorkflowId (),
311+ RunID : execution .GetRunId (),
312+ })
313+ s .NoError (err )
314+ }
255315
256- err = backoff .ThrottleRetry (namespaceExistsOp , namespaceExistsPolicy , func (_ error ) bool { return true })
316+ delResp , err := s .operatorClient .DeleteNamespace (ctx , & operatorservice.DeleteNamespaceRequest {
317+ Namespace : "ns_name_los_angeles" ,
318+ })
319+ s .NoError (err )
320+ s .Equal ("ns_name_los_angeles-deleted-" + nsID [:5 ], delResp .GetDeletedNamespace ())
321+
322+ descResp2 , err := s .frontendClient .DescribeNamespace (ctx , & workflowservice.DescribeNamespaceRequest {
323+ Id : nsID ,
324+ })
257325 s .NoError (err )
326+ s .Equal (enumspb .NAMESPACE_STATE_DELETED , descResp2 .GetNamespaceInfo ().GetState ())
327+
328+ s .Eventually (func () bool {
329+ _ , err := s .frontendClient .DescribeNamespace (ctx , & workflowservice.DescribeNamespaceRequest {
330+ Id : nsID ,
331+ })
332+ var notFound * serviceerror.NamespaceNotFound
333+ if ! errors .As (err , & notFound ) {
334+ return false // namespace still exists
335+ }
336+
337+ for _ , execution := range executions {
338+ _ , err = s .frontendClient .DescribeWorkflowExecution (ctx , & workflowservice.DescribeWorkflowExecutionRequest {
339+ Namespace : "ns_name_los_angeles" ,
340+ Execution : & commonpb.WorkflowExecution {
341+ WorkflowId : execution .GetWorkflowId (),
342+ },
343+ })
344+ if ! errors .As (err , & notFound ) {
345+ return false // should never happen
346+ }
347+ }
348+ return true
349+ }, 20 * time .Second , time .Second )
258350}
259351
260352func (s * namespaceTestSuite ) Test_NamespaceDelete_CrossNamespaceChild () {
0 commit comments