github.com/grafana/pyroscope@v1.18.0/pkg/metastore/compaction/scheduler/schedule_test.go (about) 1 package scheduler 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/hashicorp/raft" 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/mock" 10 "github.com/stretchr/testify/require" 11 12 metastorev1 "github.com/grafana/pyroscope/api/gen/proto/go/metastore/v1" 13 "github.com/grafana/pyroscope/api/gen/proto/go/metastore/v1/raft_log" 14 "github.com/grafana/pyroscope/pkg/test" 15 "github.com/grafana/pyroscope/pkg/test/mocks/mockscheduler" 16 ) 17 18 func TestSchedule_Update_LeaseRenewal(t *testing.T) { 19 store := new(mockscheduler.MockJobStore) 20 config := Config{ 21 MaxFailures: 3, 22 LeaseDuration: 10 * time.Second, 23 } 24 25 scheduler := NewScheduler(config, store, nil) 26 scheduler.queue.put(&raft_log.CompactionJobState{ 27 Name: "1", 28 CompactionLevel: 0, 29 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, 30 Token: 1, 31 LeaseExpiresAt: 0, 32 }) 33 34 t.Run("Owner", test.AssertIdempotentSubtest(t, func(t *testing.T) { 35 s := scheduler.NewSchedule(nil, &raft.Log{Index: 1, AppendedAt: time.Unix(0, 0)}) 36 update := s.UpdateJob(&raft_log.CompactionJobStatusUpdate{ 37 Name: "1", 38 Token: 1, 39 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, 40 }) 41 assert.Equal(t, &raft_log.CompactionJobState{ 42 Name: "1", 43 CompactionLevel: 0, 44 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, 45 Token: 1, 46 LeaseExpiresAt: int64(config.LeaseDuration), 47 }, update) 48 })) 49 50 t.Run("NotOwner", test.AssertIdempotentSubtest(t, func(t *testing.T) { 51 s := scheduler.NewSchedule(nil, &raft.Log{Index: 1, AppendedAt: time.Unix(0, 0)}) 52 assert.Nil(t, s.UpdateJob(&raft_log.CompactionJobStatusUpdate{ 53 Name: "1", 54 Token: 0, 55 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, 56 })) 57 })) 58 59 t.Run("JobCompleted", test.AssertIdempotentSubtest(t, func(t *testing.T) { 60 s := scheduler.NewSchedule(nil, &raft.Log{Index: 1, AppendedAt: time.Unix(0, 0)}) 61 assert.Nil(t, s.UpdateJob(&raft_log.CompactionJobStatusUpdate{ 62 Name: "0", 63 Token: 1, 64 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, 65 })) 66 })) 67 68 t.Run("WrongStatus", test.AssertIdempotentSubtest(t, func(t *testing.T) { 69 s := scheduler.NewSchedule(nil, &raft.Log{Index: 1, AppendedAt: time.Unix(0, 0)}) 70 assert.Nil(t, s.UpdateJob(&raft_log.CompactionJobStatusUpdate{ 71 Name: "1", 72 Token: 1, 73 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_UNSPECIFIED, 74 })) 75 })) 76 } 77 78 func TestSchedule_Update_JobCompleted(t *testing.T) { 79 store := new(mockscheduler.MockJobStore) 80 config := Config{ 81 MaxFailures: 3, 82 LeaseDuration: 10 * time.Second, 83 } 84 85 scheduler := NewScheduler(config, store, nil) 86 scheduler.queue.put(&raft_log.CompactionJobState{ 87 Name: "1", 88 CompactionLevel: 1, 89 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, 90 Token: 1, 91 }) 92 93 t.Run("Owner", test.AssertIdempotentSubtest(t, func(t *testing.T) { 94 s := scheduler.NewSchedule(nil, &raft.Log{Index: 1, AppendedAt: time.Unix(0, 0)}) 95 update := s.UpdateJob(&raft_log.CompactionJobStatusUpdate{ 96 Name: "1", 97 Token: 1, 98 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_SUCCESS, 99 }) 100 assert.Equal(t, &raft_log.CompactionJobState{ 101 Name: "1", 102 CompactionLevel: 1, 103 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_SUCCESS, 104 Token: 1, 105 }, update) 106 })) 107 108 t.Run("NotOwner", test.AssertIdempotentSubtest(t, func(t *testing.T) { 109 s := scheduler.NewSchedule(nil, &raft.Log{Index: 1, AppendedAt: time.Unix(0, 0)}) 110 assert.Nil(t, s.UpdateJob(&raft_log.CompactionJobStatusUpdate{ 111 Name: "1", 112 Token: 0, 113 Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_SUCCESS, 114 })) 115 })) 116 } 117 118 func TestSchedule_Assign(t *testing.T) { 119 store := new(mockscheduler.MockJobStore) 120 config := Config{ 121 MaxFailures: 3, 122 LeaseDuration: 10 * time.Second, 123 } 124 125 scheduler := NewScheduler(config, store, nil) 126 // The job plans are accessed when it's getting assigned. 127 // Their content is not important for the test. 128 plans := []*raft_log.CompactionJobPlan{ 129 {Name: "2", CompactionLevel: 0}, 130 {Name: "3", CompactionLevel: 0}, 131 {Name: "1", CompactionLevel: 1}, 132 } 133 for _, p := range plans { 134 store.On("GetJobPlan", mock.Anything, p.Name).Return(p, nil) 135 } 136 137 states := []*raft_log.CompactionJobState{ 138 {Name: "1", CompactionLevel: 1, Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_UNSPECIFIED}, 139 {Name: "2", CompactionLevel: 0, Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_UNSPECIFIED}, 140 {Name: "3", CompactionLevel: 0, Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_UNSPECIFIED}, 141 {Name: "4", CompactionLevel: 0, Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS}, 142 {Name: "5", CompactionLevel: 0, Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS}, 143 } 144 for _, s := range states { 145 scheduler.queue.put(s) 146 } 147 148 test.AssertIdempotent(t, func(t *testing.T) { 149 s := scheduler.NewSchedule(nil, &raft.Log{Index: 1, AppendedAt: time.Unix(0, 0)}) 150 for j := range plans { 151 update, err := s.AssignJob() 152 require.NoError(t, err) 153 assert.Equal(t, plans[j], update.Plan) 154 assert.Equal(t, metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, update.State.Status) 155 assert.Equal(t, int64(config.LeaseDuration), update.State.LeaseExpiresAt) 156 assert.Equal(t, uint64(1), update.State.Token) 157 } 158 159 update, err := s.AssignJob() 160 require.NoError(t, err) 161 assert.Nil(t, update) 162 }) 163 } 164 165 func TestSchedule_ReAssign(t *testing.T) { 166 store := new(mockscheduler.MockJobStore) 167 config := Config{ 168 MaxFailures: 3, 169 LeaseDuration: 10 * time.Second, 170 } 171 172 scheduler := NewScheduler(config, store, nil) 173 plans := []*raft_log.CompactionJobPlan{ 174 {Name: "1"}, 175 {Name: "2"}, 176 {Name: "3"}, 177 {Name: "4"}, 178 {Name: "5"}, 179 {Name: "6"}, 180 } 181 for _, p := range plans { 182 store.On("GetJobPlan", mock.Anything, p.Name).Return(p, nil) 183 } 184 185 now := int64(5) 186 states := []*raft_log.CompactionJobState{ 187 // Jobs with expired leases (now > LeaseExpiresAt). 188 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 1}, 189 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 1}, 190 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 1}, 191 // This job can't be reassigned as its lease is still valid. 192 {Name: "4", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 10}, 193 // The job has already failed in the past. 194 {Name: "5", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 1, Failures: 1}, 195 // The job has already failed in the past and exceeded the error threshold. 196 {Name: "6", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 1, Failures: 3}, 197 } 198 for _, s := range states { 199 scheduler.queue.put(s) 200 } 201 202 lease := now + int64(config.LeaseDuration) 203 expected := []*raft_log.CompactionJobState{ 204 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 2, LeaseExpiresAt: lease, Failures: 1}, 205 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 2, LeaseExpiresAt: lease, Failures: 1}, 206 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 2, LeaseExpiresAt: lease, Failures: 1}, 207 {Name: "5", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 2, LeaseExpiresAt: lease, Failures: 2}, 208 } 209 210 test.AssertIdempotent(t, func(t *testing.T) { 211 s := scheduler.NewSchedule(nil, &raft.Log{Index: 2, AppendedAt: time.Unix(0, now)}) 212 assigned := make([]*raft_log.CompactionJobState, 0, len(expected)) 213 for { 214 update, err := s.AssignJob() 215 require.NoError(t, err) 216 if update == nil { 217 break 218 } 219 assigned = append(assigned, update.State) 220 } 221 222 assert.Equal(t, expected, assigned) 223 }) 224 } 225 226 func TestSchedule_UpdateAssign(t *testing.T) { 227 store := new(mockscheduler.MockJobStore) 228 config := Config{ 229 MaxFailures: 3, 230 LeaseDuration: 10 * time.Second, 231 } 232 233 scheduler := NewScheduler(config, store, nil) 234 plans := []*raft_log.CompactionJobPlan{ 235 {Name: "1"}, 236 {Name: "2"}, 237 {Name: "3"}, 238 } 239 for _, p := range plans { 240 store.On("GetJobPlan", mock.Anything, p.Name).Return(p, nil) 241 } 242 243 states := []*raft_log.CompactionJobState{ 244 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0}, 245 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0}, 246 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0}, 247 } 248 for _, s := range states { 249 scheduler.queue.put(s) 250 } 251 252 // Lease is extended without reassignment if update arrives after the 253 // expiration, but this is the first worker requested assignment. 254 test.AssertIdempotent(t, func(t *testing.T) { 255 updates := []*raft_log.CompactionJobStatusUpdate{ 256 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1}, 257 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1}, 258 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1}, 259 } 260 261 updatedAt := time.Second * 20 262 s := scheduler.NewSchedule(nil, &raft.Log{Index: 2, AppendedAt: time.Unix(0, int64(updatedAt))}) 263 for i := range updates { 264 update := s.UpdateJob(updates[i]) 265 assert.Equal(t, metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, update.Status) 266 assert.Equal(t, int64(updatedAt)+int64(config.LeaseDuration), update.LeaseExpiresAt) 267 assert.Equal(t, uint64(1), update.Token) // Token must not change. 268 } 269 270 update, err := s.AssignJob() 271 require.NoError(t, err) 272 assert.Nil(t, update) 273 }) 274 275 // If the worker reports success status and its lease has expired but the 276 // job has not been reassigned, we accept the results. 277 test.AssertIdempotent(t, func(t *testing.T) { 278 updates := []*raft_log.CompactionJobStatusUpdate{ 279 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_SUCCESS, Token: 1}, 280 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_SUCCESS, Token: 1}, 281 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_SUCCESS, Token: 1}, 282 } 283 284 updatedAt := time.Second * 20 285 s := scheduler.NewSchedule(nil, &raft.Log{Index: 2, AppendedAt: time.Unix(0, int64(updatedAt))}) 286 for i := range updates { 287 assert.NotNil(t, s.UpdateJob(updates[i])) 288 } 289 290 update, err := s.AssignJob() 291 require.NoError(t, err) 292 assert.Nil(t, update) 293 }) 294 295 // The worker may be reassigned with the jobs it abandoned, 296 // if it requested assignments first. 297 test.AssertIdempotent(t, func(t *testing.T) { 298 updatedAt := time.Second * 20 299 s := scheduler.NewSchedule(nil, &raft.Log{Index: 2, AppendedAt: time.Unix(0, int64(updatedAt))}) 300 for range plans { 301 update, err := s.AssignJob() 302 require.NoError(t, err) 303 assert.NotNil(t, update.State) 304 assert.NotNil(t, update.Plan) 305 assert.Equal(t, int64(updatedAt)+int64(config.LeaseDuration), update.State.LeaseExpiresAt) 306 assert.Equal(t, uint64(2), update.State.Token) // Token must change. 307 } 308 309 update, err := s.AssignJob() 310 require.NoError(t, err) 311 assert.Nil(t, update) 312 }) 313 } 314 315 func TestSchedule_Add(t *testing.T) { 316 store := new(mockscheduler.MockJobStore) 317 config := Config{ 318 MaxFailures: 3, 319 LeaseDuration: 10 * time.Second, 320 } 321 322 scheduler := NewScheduler(config, store, nil) 323 plans := []*raft_log.CompactionJobPlan{ 324 {Name: "1"}, 325 {Name: "2"}, 326 {Name: "3"}, 327 } 328 329 states := []*raft_log.CompactionJobState{ 330 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_UNSPECIFIED, AddedAt: 1, Token: 1}, 331 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_UNSPECIFIED, AddedAt: 1, Token: 1}, 332 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_UNSPECIFIED, AddedAt: 1, Token: 1}, 333 } 334 335 test.AssertIdempotent(t, func(t *testing.T) { 336 s := scheduler.NewSchedule(nil, &raft.Log{Index: 1, AppendedAt: time.Unix(0, 1)}) 337 for i := range plans { 338 assert.Equal(t, states[i], s.AddJob(plans[i])) 339 } 340 }) 341 } 342 343 func TestSchedule_QueueSizeLimit(t *testing.T) { 344 store := new(mockscheduler.MockJobStore) 345 config := Config{ 346 MaxQueueSize: 2, 347 MaxFailures: 3, 348 LeaseDuration: 10 * time.Second, 349 } 350 351 scheduler := NewScheduler(config, store, nil) 352 plans := []*raft_log.CompactionJobPlan{ 353 {Name: "1"}, 354 {Name: "2"}, 355 {Name: "3"}, 356 } 357 358 states := []*raft_log.CompactionJobState{ 359 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_UNSPECIFIED, AddedAt: 1, Token: 1}, 360 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_UNSPECIFIED, AddedAt: 1, Token: 1}, 361 } 362 363 test.AssertIdempotent(t, func(t *testing.T) { 364 s := scheduler.NewSchedule(nil, &raft.Log{Index: 1, AppendedAt: time.Unix(0, 1)}) 365 assert.Equal(t, states[0], s.AddJob(plans[0])) 366 assert.Equal(t, states[1], s.AddJob(plans[1])) 367 assert.Nil(t, s.AddJob(plans[2])) 368 }) 369 } 370 371 func TestSchedule_AssignEvict(t *testing.T) { 372 store := new(mockscheduler.MockJobStore) 373 config := Config{ 374 MaxQueueSize: 2, 375 MaxFailures: 3, 376 LeaseDuration: 10 * time.Second, 377 } 378 379 scheduler := NewScheduler(config, store, nil) 380 plans := []*raft_log.CompactionJobPlan{ 381 {Name: "4"}, 382 } 383 for _, p := range plans { 384 store.On("GetJobPlan", mock.Anything, p.Name).Return(p, nil) 385 } 386 387 states := []*raft_log.CompactionJobState{ 388 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 389 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 390 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 391 {Name: "4", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 0}, 392 } 393 for _, s := range states { 394 scheduler.queue.put(s) 395 } 396 397 test.AssertIdempotent(t, func(t *testing.T) { 398 updatedAt := time.Second * 20 399 s := scheduler.NewSchedule(nil, &raft.Log{Index: 2, AppendedAt: time.Unix(0, int64(updatedAt))}) 400 // Eviction is only possible when no jobs are available for assignment. 401 assert.Nil(t, s.EvictJob()) 402 // Assign all the available jobs. 403 update, err := s.AssignJob() 404 require.NoError(t, err) 405 assert.Equal(t, "4", update.State.Name) 406 update, err = s.AssignJob() 407 require.NoError(t, err) 408 assert.Nil(t, update) 409 // Now that no jobs can be assigned, we can try eviction. 410 assert.NotNil(t, s.EvictJob()) 411 assert.NotNil(t, s.EvictJob()) 412 // MaxQueueSize reached. 413 assert.Nil(t, s.EvictJob()) 414 }) 415 } 416 417 func TestSchedule_Evict(t *testing.T) { 418 store := new(mockscheduler.MockJobStore) 419 config := Config{ 420 MaxQueueSize: 2, 421 MaxFailures: 3, 422 LeaseDuration: 10 * time.Second, 423 } 424 425 scheduler := NewScheduler(config, store, nil) 426 states := []*raft_log.CompactionJobState{ 427 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 428 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 429 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 430 } 431 for _, s := range states { 432 scheduler.queue.put(s) 433 } 434 435 test.AssertIdempotent(t, func(t *testing.T) { 436 updatedAt := time.Second * 20 437 s := scheduler.NewSchedule(nil, &raft.Log{Index: 2, AppendedAt: time.Unix(0, int64(updatedAt))}) 438 // Eviction is only possible when no jobs are available for assignment. 439 update, err := s.AssignJob() 440 require.NoError(t, err) 441 assert.Nil(t, update) 442 assert.NotNil(t, s.EvictJob()) 443 assert.Nil(t, s.EvictJob()) 444 }) 445 } 446 447 func TestSchedule_NoEvict(t *testing.T) { 448 store := new(mockscheduler.MockJobStore) 449 config := Config{ 450 MaxQueueSize: 5, 451 MaxFailures: 3, 452 LeaseDuration: 10 * time.Second, 453 } 454 455 scheduler := NewScheduler(config, store, nil) 456 states := []*raft_log.CompactionJobState{ 457 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 458 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 459 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 460 } 461 for _, s := range states { 462 scheduler.queue.put(s) 463 } 464 465 test.AssertIdempotent(t, func(t *testing.T) { 466 updatedAt := time.Second * 20 467 s := scheduler.NewSchedule(nil, &raft.Log{Index: 2, AppendedAt: time.Unix(0, int64(updatedAt))}) 468 // Eviction is only possible when no jobs are available for assignment. 469 update, err := s.AssignJob() 470 require.NoError(t, err) 471 assert.Nil(t, update) 472 // Eviction is only possible when the queue size limit is reached. 473 assert.Nil(t, s.EvictJob()) 474 }) 475 } 476 477 func TestSchedule_NoEvictNoQueueSizeLimit(t *testing.T) { 478 store := new(mockscheduler.MockJobStore) 479 config := Config{ 480 MaxQueueSize: 0, 481 MaxFailures: 3, 482 LeaseDuration: 10 * time.Second, 483 } 484 485 scheduler := NewScheduler(config, store, nil) 486 states := []*raft_log.CompactionJobState{ 487 {Name: "1", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 488 {Name: "2", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 489 {Name: "3", Status: metastorev1.CompactionJobStatus_COMPACTION_STATUS_IN_PROGRESS, Token: 1, LeaseExpiresAt: 0, Failures: 3}, 490 } 491 for _, s := range states { 492 scheduler.queue.put(s) 493 } 494 495 test.AssertIdempotent(t, func(t *testing.T) { 496 updatedAt := time.Second * 20 497 s := scheduler.NewSchedule(nil, &raft.Log{Index: 2, AppendedAt: time.Unix(0, int64(updatedAt))}) 498 // Eviction is only possible when no jobs are available for assignment. 499 update, err := s.AssignJob() 500 require.NoError(t, err) 501 assert.Nil(t, update) 502 // Eviction is not possible if the queue size limit is not set. 503 assert.Nil(t, s.EvictJob()) 504 }) 505 }