fix(worker): deduplicate check result replays
Все проверки выполнены успешно
CI / test (push) Successful in 2m7s
Docker / Build and publish worker image (push) Successful in 22m17s
Все проверки выполнены успешно
CI / test (push) Successful in 2m7s
Docker / Build and publish worker image (push) Successful in 22m17s
Этот коммит содержится в:
@@ -161,6 +161,85 @@ func TestApplyRemoteCheckResult_DirectWhenQuorumOne(t *testing.T) {
|
||||
"the region result row is always inserted even on the legacy path")
|
||||
}
|
||||
|
||||
func TestApplyRemoteCheckResultFromWorkerDeduplicatesFailureReplay(t *testing.T) {
|
||||
models.Drop()
|
||||
models.Migrate()
|
||||
|
||||
mon, check := seedAggregatorWorld(t, 1, 5)
|
||||
seedRegion(t, "ru-msk")
|
||||
worker := models.WorkerNode{
|
||||
WorkerID: "replay-worker",
|
||||
RegionCode: "ru-msk",
|
||||
AuthToken: "replay-token",
|
||||
}
|
||||
require.NoError(t, models.DB().Create(&worker).Error)
|
||||
report := makeReport(check.ID, mon.ID, "ERR")
|
||||
report.JobID = "same-failed-execution"
|
||||
|
||||
require.NoError(t, models.ApplyRemoteCheckResultFromWorker(report, worker.RegionCode, &worker))
|
||||
require.NoError(t, models.ApplyRemoteCheckResultFromWorker(report, worker.RegionCode, &worker))
|
||||
|
||||
got := loadCheck(t, check.ID)
|
||||
assert.Equal(t, 1, got.Fails)
|
||||
assert.EqualValues(t, 1, countPendingResults(t, check.ID))
|
||||
var attempts int64
|
||||
require.NoError(t, models.DB().Model(&models.CheckAttempt{}).Where("job_id = ?", report.JobID).Count(&attempts).Error)
|
||||
assert.EqualValues(t, 1, attempts)
|
||||
}
|
||||
|
||||
func TestApplyRemoteCheckResultFromWorkerDeduplicatesQuorumReplay(t *testing.T) {
|
||||
models.Drop()
|
||||
models.Migrate()
|
||||
|
||||
mon, check := seedAggregatorWorld(t, 2, 5)
|
||||
seedRegion(t, "ru-msk")
|
||||
worker := models.WorkerNode{
|
||||
WorkerID: "quorum-replay-worker",
|
||||
RegionCode: "ru-msk",
|
||||
AuthToken: "quorum-replay-token",
|
||||
}
|
||||
require.NoError(t, models.DB().Create(&worker).Error)
|
||||
report := makeReport(check.ID, mon.ID, "OK")
|
||||
report.JobID = "same-quorum-execution"
|
||||
|
||||
require.NoError(t, models.ApplyRemoteCheckResultFromWorker(report, worker.RegionCode, &worker))
|
||||
require.NoError(t, models.ApplyRemoteCheckResultFromWorker(report, worker.RegionCode, &worker))
|
||||
|
||||
got := loadCheck(t, check.ID)
|
||||
assert.Equal(t, "UNK", got.State, "quorum state remains owned by the aggregator")
|
||||
assert.EqualValues(t, 1, countPendingResults(t, check.ID))
|
||||
var attempts int64
|
||||
require.NoError(t, models.DB().Model(&models.CheckAttempt{}).Where("job_id = ?", report.JobID).Count(&attempts).Error)
|
||||
assert.EqualValues(t, 1, attempts)
|
||||
}
|
||||
|
||||
func TestApplyRemoteCheckResultFromWorkerDeduplicatesFailReplay(t *testing.T) {
|
||||
models.Drop()
|
||||
models.Migrate()
|
||||
|
||||
mon, check := seedAggregatorWorld(t, 1, 5)
|
||||
seedRegion(t, "ru-msk")
|
||||
worker := models.WorkerNode{
|
||||
WorkerID: "fail-replay-worker",
|
||||
RegionCode: "ru-msk",
|
||||
AuthToken: "fail-replay-token",
|
||||
}
|
||||
require.NoError(t, models.DB().Create(&worker).Error)
|
||||
report := makeReport(check.ID, mon.ID, "FAIL")
|
||||
report.JobID = "same-fail-execution"
|
||||
|
||||
require.NoError(t, models.ApplyRemoteCheckResultFromWorker(report, worker.RegionCode, &worker))
|
||||
require.NoError(t, models.ApplyRemoteCheckResultFromWorker(report, worker.RegionCode, &worker))
|
||||
|
||||
got := loadCheck(t, check.ID)
|
||||
assert.Equal(t, "FAIL", got.State)
|
||||
assert.Equal(t, 0, got.Fails, "FAIL resets consecutive ERR tracking")
|
||||
assert.EqualValues(t, 1, countPendingResults(t, check.ID))
|
||||
var attempts int64
|
||||
require.NoError(t, models.DB().Model(&models.CheckAttempt{}).Where("job_id = ?", report.JobID).Count(&attempts).Error)
|
||||
assert.EqualValues(t, 1, attempts)
|
||||
}
|
||||
|
||||
// TestApplyRemoteCheckResult_BuffersWhenQuorumN pins the new path:
|
||||
// when RequireQuorum > 1, ApplyRemoteCheckResult does NOT touch
|
||||
// Check.State — it only inserts the CheckRegionResult row. The check
|
||||
|
||||
Ссылка в новой задаче
Block a user