github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/job/mem_scheduler_test.go (about) 1 package job_test 2 3 import ( 4 "context" 5 "sync/atomic" 6 "testing" 7 "time" 8 9 "github.com/cozy/cozy-stack/model/job" 10 "github.com/cozy/cozy-stack/pkg/config/config" 11 "github.com/cozy/cozy-stack/pkg/couchdb" 12 "github.com/cozy/cozy-stack/pkg/realtime" 13 "github.com/cozy/cozy-stack/tests/testutils" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestMemScheduler(t *testing.T) { 19 if testing.Short() { 20 t.Skip("an instance is required for this test: test skipped due to the use of --short flag") 21 } 22 23 config.UseTestFile(t) 24 setup := testutils.NewSetup(t, t.Name()) 25 testInstance := setup.GetTestInstance() 26 27 t.Run("TriggersBadArguments", func(t *testing.T) { 28 var err error 29 _, err = job.NewTrigger(testInstance, job.TriggerInfos{ 30 Type: "@at", 31 Arguments: "garbage", 32 }, nil) 33 assert.Error(t, err) 34 35 _, err = job.NewTrigger(testInstance, job.TriggerInfos{ 36 Type: "@in", 37 Arguments: "garbage", 38 }, nil) 39 assert.Error(t, err) 40 41 _, err = job.NewTrigger(testInstance, job.TriggerInfos{ 42 Type: "@unknown", 43 Arguments: "", 44 }, nil) 45 if assert.Error(t, err) { 46 assert.Equal(t, job.ErrUnknownTrigger, err) 47 } 48 }) 49 50 t.Run("MemSchedulerWithDebounce", func(t *testing.T) { 51 var called int32 52 bro := job.NewMemBroker() 53 assert.NoError(t, bro.StartWorkers(job.WorkersList{ 54 { 55 WorkerType: "worker", 56 Concurrency: 1, 57 MaxExecCount: 1, 58 Timeout: 1 * time.Millisecond, 59 WorkerFunc: func(_ *job.TaskContext) error { 60 atomic.AddInt32(&called, 1) 61 return nil 62 }, 63 }, 64 })) 65 66 msg, _ := job.NewMessage("@event") 67 ti := job.TriggerInfos{ 68 Type: "@event", 69 Arguments: "io.cozy.testdebounce io.cozy.moredebounce", 70 Debounce: "2s", 71 WorkerType: "worker", 72 Message: msg, 73 } 74 75 var triggers []job.Trigger 76 triggersInfos := []job.TriggerInfos{ti} 77 sch := job.NewMemScheduler() 78 if !assert.NoError(t, sch.StartScheduler(bro)) { 79 return 80 } 81 82 // Clear the existing triggers before testing with our triggers 83 ts, err := sch.GetAllTriggers(testInstance) 84 assert.NoError(t, err) 85 for _, trigger := range ts { 86 err = sch.DeleteTrigger(testInstance, trigger.ID()) 87 assert.NoError(t, err) 88 } 89 90 for _, infos := range triggersInfos { 91 trigger, err := job.NewTrigger(testInstance, infos, msg) 92 require.NoError(t, err) 93 94 err = sch.AddTrigger(trigger) 95 require.NoError(t, err) 96 97 triggers = append(triggers, trigger) 98 } 99 100 ts, err = sch.GetAllTriggers(testInstance) 101 assert.NoError(t, err) 102 assert.Len(t, ts, len(triggers)) 103 104 doc := &couchdb.JSONDoc{ 105 Type: "io.cozy.testdebounce", 106 M: map[string]interface{}{ 107 "_id": "test-id", 108 "_rev": "1-xxabxx", 109 "test": "value", 110 }, 111 } 112 113 for i := 0; i < 24; i++ { 114 time.Sleep(200 * time.Millisecond) 115 realtime.GetHub().Publish(testInstance, realtime.EventCreate, doc, nil) 116 } 117 118 time.Sleep(3000 * time.Millisecond) 119 assert.Equal(t, int32(3), atomic.LoadInt32(&called)) 120 121 doc2 := doc.Clone().(*couchdb.JSONDoc) 122 doc2.Type = "io.cozy.moredebounce" 123 realtime.GetHub().Publish(testInstance, realtime.EventCreate, doc, nil) 124 realtime.GetHub().Publish(testInstance, realtime.EventCreate, doc2, nil) 125 time.Sleep(3000 * time.Millisecond) 126 assert.Equal(t, int32(4), atomic.LoadInt32(&called)) 127 128 for _, trigger := range triggers { 129 err = sch.DeleteTrigger(testInstance, trigger.ID()) 130 assert.NoError(t, err) 131 } 132 133 err = sch.ShutdownScheduler(context.Background()) 134 assert.NoError(t, err) 135 }) 136 }