Skip to content

Commit 9648502

Browse files
authored
Fix control run state failures for databricks_job resource (#3585)
* work * Tolerate 409 in RunNow() call for jobs * fmt
1 parent 8b29d2d commit 9648502

File tree

2 files changed

+68
-9
lines changed

2 files changed

+68
-9
lines changed

jobs/resource_job.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strings"
1111
"time"
1212

13+
"github.com/databricks/databricks-sdk-go"
1314
"github.com/databricks/databricks-sdk-go/service/compute"
1415
"github.com/databricks/databricks-sdk-go/service/jobs"
1516

@@ -1000,17 +1001,17 @@ func (c controlRunStateLifecycleManager) OnUpdate(ctx context.Context) error {
10001001
// on a continuous job works, cancelling the active run if there is one, and resetting
10011002
// the exponential backoff timer. So, we try to call RunNow() first, and if it fails,
10021003
// we call StopActiveRun() instead.
1004+
//
1005+
// If there was no active run before the update, Jobs will start a run after the update.
1006+
// This RunNow() call can race with this automatic trigger, in which case, a 409 Conflict
1007+
// is returned. The provider can safely ignore this, as a new run will have started
1008+
// anyways.
10031009
_, err = api.RunNow(jobID)
10041010

1005-
if err == nil {
1011+
if err == nil || errors.Is(err, databricks.ErrNotFound) || errors.Is(err, databricks.ErrResourceConflict) {
10061012
return nil
10071013
}
1008-
1009-
// RunNow() returns 404 when the feature is disabled.
1010-
var apiErr *apierr.APIError
1011-
if errors.As(err, &apiErr) && apiErr.StatusCode != 404 {
1012-
return err
1013-
}
1014+
return err
10141015
}
10151016

10161017
return api.StopActiveRun(jobID, c.d.Timeout(schema.TimeoutUpdate))

jobs/resource_job_test.go

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,7 @@ func TestResourceJobCreate_Trigger_TableUpdateCreate(t *testing.T) {
13811381
}.Apply(t)
13821382
}
13831383

1384-
func TestResourceJobCreate_ControlRunState_ContinuousUpdateRunNow(t *testing.T) {
1384+
func TestResourceJobUpdate_ControlRunState_ContinuousUpdateRunNow(t *testing.T) {
13851385
qa.ResourceFixture{
13861386
Update: true,
13871387
ID: "789",
@@ -1432,7 +1432,65 @@ func TestResourceJobCreate_ControlRunState_ContinuousUpdateRunNow(t *testing.T)
14321432
max_concurrent_runs = 1
14331433
name = "Test"
14341434
`,
1435-
}.Apply(t)
1435+
}.ApplyNoError(t)
1436+
}
1437+
1438+
func TestResourceJobUpdate_ControlRunState_ContinuousUpdateRunNowFailsWith409(t *testing.T) {
1439+
qa.ResourceFixture{
1440+
Update: true,
1441+
ID: "789",
1442+
Resource: ResourceJob(),
1443+
Fixtures: []qa.HTTPFixture{
1444+
{
1445+
Method: "POST",
1446+
Resource: "/api/2.0/jobs/reset",
1447+
ExpectedRequest: UpdateJobRequest{
1448+
JobID: 789,
1449+
NewSettings: &JobSettings{
1450+
MaxConcurrentRuns: 1,
1451+
Name: "Test",
1452+
Continuous: &ContinuousConf{
1453+
PauseStatus: "UNPAUSED",
1454+
},
1455+
},
1456+
},
1457+
},
1458+
{
1459+
Method: "GET",
1460+
Resource: "/api/2.0/jobs/get?job_id=789",
1461+
Response: Job{
1462+
JobID: 789,
1463+
Settings: &JobSettings{
1464+
MaxConcurrentRuns: 1,
1465+
Name: "Test",
1466+
Continuous: &ContinuousConf{
1467+
PauseStatus: "UNPAUSED",
1468+
},
1469+
},
1470+
},
1471+
},
1472+
{
1473+
Method: "POST",
1474+
Resource: "/api/2.0/jobs/run-now",
1475+
ExpectedRequest: RunParameters{
1476+
JobID: 789,
1477+
},
1478+
Status: 409,
1479+
Response: apierr.APIErrorBody{
1480+
ErrorCode: "CONFLICT",
1481+
Message: "A concurrent request to run the continuous job is already in progress. Please wait for it to complete before issuing a new request.",
1482+
},
1483+
},
1484+
},
1485+
HCL: `
1486+
continuous {
1487+
pause_status = "UNPAUSED"
1488+
}
1489+
control_run_state = true
1490+
max_concurrent_runs = 1
1491+
name = "Test"
1492+
`,
1493+
}.ApplyNoError(t)
14361494
}
14371495

14381496
func TestResourceJobCreate_ControlRunState_ContinuousUpdateCancel(t *testing.T) {

0 commit comments

Comments
 (0)