diff --git a/.github/workflows/ci.yml b/.github/workflows/ci-tests.yml similarity index 84% rename from .github/workflows/ci.yml rename to .github/workflows/ci-tests.yml index b6b3247..fb647f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci-tests.yml @@ -9,8 +9,8 @@ on: - main env: - GO_VERSION: 1.25.1 - GOLANGCI_LINT_VERSION: v2.4.0 + GO_VERSION: 1.25.3 + GOLANGCI_LINT_VERSION: v2.5.0 jobs: golangci: @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: ${{ env.GO_VERSION }} @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: ${{ env.GO_VERSION }} - run: go mod download diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1f64e03..601c762 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,8 +17,8 @@ permissions: contents: write env: - GO_VERSION: 1.25.1 - GOLANGCI_LINT_VERSION: v2.4.0 + GO_VERSION: 1.25.3 + GOLANGCI_LINT_VERSION: v2.5.0 jobs: version-bump-check: @@ -70,7 +70,7 @@ jobs: with: fetch-depth: 0 # fetch all history (include tags) - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: ${{ env.GO_VERSION }} diff --git a/.golangci.yml b/.golangci.yml index 6f5574c..54a895f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,9 +8,14 @@ linters: # standard includes the 5 linters: errcheck, govet, ineffassign, staticcheck, and unused default: standard enable: - - revive + - copyloopvar - misspell + - revive settings: + copyloopvar: + check-alias: true + misspell: + locale: US revive: # See https://golangci-lint.run/usage/linters/#revive for more information. max-open-files: 2048 @@ -45,8 +50,6 @@ linters: disabled: false exclude: [TEST] arguments: [0, 80] - misspell: - locale: US issues: max-issues-per-linter: 0 diff --git a/executor_distributed.go b/executor_distributed.go index f9da118..336d01f 100644 --- a/executor_distributed.go +++ b/executor_distributed.go @@ -487,14 +487,12 @@ func (r *jobRunner) runParallel(errCh chan<- error, taskExecChan chan<- time.Dur if sem != nil { sem <- struct{}{} } - wg.Add(1) - go func(tt Task, jobID string) { - defer wg.Done() - safeExecuteTask(r.ctx, jobID, tt, errCh, taskExecChan) + wg.Go(func() { + safeExecuteTask(r.ctx, r.job.ID, t, errCh, taskExecChan) if sem != nil { <-sem } - }(t, r.job.ID) + }) } wg.Wait() diff --git a/executor_on_demand.go b/executor_on_demand.go index 3982073..87f7de0 100644 --- a/executor_on_demand.go +++ b/executor_on_demand.go @@ -570,14 +570,12 @@ func (e *onDemandExecutor) runParallel( if sem != nil { sem <- struct{}{} } - wg.Add(1) - go func(tt Task) { - defer wg.Done() - safeExecuteTask(e.ctx, jobID, tt, errCh, taskExecChan) + wg.Go(func() { + safeExecuteTask(e.ctx, jobID, t, errCh, taskExecChan) if sem != nil { <-sem } - }(t) + }) } wg.Wait() diff --git a/executor_test.go b/executor_test.go index da376e3..757ac3e 100644 --- a/executor_test.go +++ b/executor_test.go @@ -181,18 +181,15 @@ func (s *executorTestSuite) TestExecutorConcurrentSchedule(t *testing.T) { numTasksPerGoroutine := 250 for id := range numGoroutines { - wg.Add(1) - go func(id int) { - defer wg.Done() + wg.Go(func() { for j := range numTasksPerGoroutine { taskID := fmt.Sprintf("task-%d-%d", id, j) // Use a long cadence to avoid task execution before test ends job := getMockedJob(2, taskID, 2*time.Second, 2*time.Second) assert.NoError(t, exec.Schedule(job), "Error adding job concurrently") } - }(id) + }) } - wg.Wait() // Verify that all tasks are scheduled @@ -218,9 +215,7 @@ func (s *executorTestSuite) TestExecutorConcurrentExecution(t *testing.T) { var wg sync.WaitGroup errChan := make(chan error, numGoroutines*numJobsPerGoroutine) for id := range numGoroutines { - wg.Add(1) - go func(id int) { - defer wg.Done() + wg.Go(func() { for j := range numJobsPerGoroutine { jobID := fmt.Sprintf("exec-%d-%d", id, j) job := Job{ @@ -233,9 +228,10 @@ func (s *executorTestSuite) TestExecutorConcurrentExecution(t *testing.T) { errChan <- err } } - }(id) + }) } wg.Wait() + close(errChan) for err := range errChan { assert.NoError(t, err) diff --git a/go.mod b/go.mod index 11a1e60..f5da808 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module github.com/jkbrsn/taskman -go 1.25.1 +go 1.25.3 require ( - github.com/jkbrsn/threadsafe v0.5.0 + github.com/jkbrsn/threadsafe v0.6.0 github.com/rs/xid v1.6.0 github.com/rs/zerolog v1.34.0 github.com/stretchr/testify v1.10.0 @@ -14,6 +14,6 @@ require ( github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.36.0 // indirect + golang.org/x/sys v0.37.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index c407752..792be0e 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/jkbrsn/threadsafe v0.5.0 h1:Iev5+agv64qxXa0QnTUnsvMkBhicnEMQ3YsVZ+KU9cY= -github.com/jkbrsn/threadsafe v0.5.0/go.mod h1:f8lewyuKXmcsoapAekEXgoCDsM2tWPys8jiNeVC+8Kk= +github.com/jkbrsn/threadsafe v0.6.0 h1:qckP2rogbByv0IBM97yNarHFWDFIzuu2uVuMaBWzuOk= +github.com/jkbrsn/threadsafe v0.6.0/go.mod h1:ezyLMWYx9hUxTK7OAC2F6tkN/KDJ9LvtpuCa8AU6NOU= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= @@ -23,8 +23,8 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/manager.go b/manager.go index e0927e7..7f0edf7 100644 --- a/manager.go +++ b/manager.go @@ -269,10 +269,8 @@ func New(opts ...Option) *TaskManager { tm.deParallel, tm.deMaxPar, ) - case ModePool: - // Intentionally fall through as ModePool is the default - fallthrough default: + // case ModePool is the default tm.exec = newPoolExecutor( tm.ctx, tm.log, diff --git a/manager_test.go b/manager_test.go index b289f26..1346eb4 100644 --- a/manager_test.go +++ b/manager_test.go @@ -598,9 +598,7 @@ func (s *managerTestSuite) TestConcurrentScheduleTask(t *testing.T) { numTasksPerGoroutine := 250 for id := range numGoroutines { - wg.Add(1) - go func(id int) { - defer wg.Done() + wg.Go(func() { for j := range numTasksPerGoroutine { taskID := fmt.Sprintf("task-%d-%d", id, j) // Use a long cadence to avoid task execution before test ends, @@ -609,9 +607,8 @@ func (s *managerTestSuite) TestConcurrentScheduleTask(t *testing.T) { _, err := manager.ScheduleTask(task, task.cadence) assert.NoError(t, err, "Error adding task concurrently") } - }(id) + }) } - wg.Wait() // Verify that all tasks are scheduled @@ -628,9 +625,7 @@ func (s *managerTestSuite) TestConcurrentScheduleJob(t *testing.T) { numJobsPerGoroutine := 250 for id := range numGoroutines { - wg.Add(1) - go func(id int) { - defer wg.Done() + wg.Go(func() { for j := range numJobsPerGoroutine { jobID := fmt.Sprintf("job-%d-%d", id, j) // Use a long cadence to avoid job execution before test ends, @@ -639,9 +634,8 @@ func (s *managerTestSuite) TestConcurrentScheduleJob(t *testing.T) { err := manager.ScheduleJob(job) assert.NoError(t, err, "Error adding job concurrently") } - }(id) + }) } - wg.Wait() // Verify that all tasks are scheduled diff --git a/worker_pool_test.go b/worker_pool_test.go index f35a893..a9775bf 100644 --- a/worker_pool_test.go +++ b/worker_pool_test.go @@ -137,20 +137,17 @@ func TestWorkerPoolExecutionError(t *testing.T) { ID: "error-task", } - var wg sync.WaitGroup - wg.Add(1) - // Listen to the error channel, confirm error is received timeout := time.After(100 * time.Millisecond) - go func() { - defer wg.Done() + var wg sync.WaitGroup + wg.Go(func() { select { case err := <-errorChan: assert.Contains(t, err.Error(), "test error") case <-timeout: assert.Fail(t, "Test timed out waiting on error") } - }() + }) // Send the error-returning task to the worker taskChan <- errorTask @@ -187,13 +184,10 @@ func TestWorkerPoolExecutionPanic(t *testing.T) { ID: "panic-task", } - var wg sync.WaitGroup - wg.Add(1) - // Listen to the error channel, confirm error is received timeout := time.After(100 * time.Millisecond) - go func() { - defer wg.Done() + var wg sync.WaitGroup + wg.Go(func() { select { case err := <-errorChan: assert.Contains(t, err.Error(), "panic:") @@ -201,7 +195,7 @@ func TestWorkerPoolExecutionPanic(t *testing.T) { case <-timeout: assert.Fail(t, "Test timed out waiting on error") } - }() + }) // Send the panic-returning task to the worker taskChan <- panicTask