Skip to content
This repository has been archived by the owner on Mar 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #110 from im-kulikov/internal_context_for_service_…
Browse files Browse the repository at this point in the history
…group

Internal context for service group
  • Loading branch information
im-kulikov committed Jan 16, 2022
2 parents e49b3b8 + 743355a commit ec311ad
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 17 deletions.
33 changes: 22 additions & 11 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
linters:
enable-all: true
enable-all: false
enable:
- unparam
- whitespace
- unconvert
- bodyclose
- gofmt
- gocritic
- godot
- prealloc
- rowserrcheck
- unconvert
- lll
- cyclop
- gci
- gosec
- prealloc
- revive
- gochecknoglobals
- funlen
disable:
- testpackage
- wrapcheck
- interfacer
- scopelint
- maligned
- paralleltest
- tparallel
- stylecheck
- golint
- exhaustivestruct
- errcheck
- ineffassign

linters-settings:
govet:
Expand Down
15 changes: 9 additions & 6 deletions group/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,26 +95,29 @@ func (g *group) Run(ctx context.Context) error {
var (
cnt int
err error
top = ctx
res = make(chan error, len(g.services))
)

// we should add cancel to prevent service freeze
top, cancel := context.WithCancel(ctx)

// run all services
for i := range g.services {
go func(callback Callback) { res <- callback(ctx) }(g.services[i].callback)
go func(callback Callback) { res <- callback(top) }(g.services[i].callback)
}

// wait for context.Done() or error will be received:
select {
case err = <-res:
cnt = 1 // first error received, ignore it in future
case <-ctx.Done():
err = ctx.Err()
top = context.Background()
case <-top.Done():
err = top.Err()
}

cancel()

// prepare graceful context to stop
grace, stop := context.WithTimeout(top, g.shutdown)
grace, stop := context.WithTimeout(context.Background(), g.shutdown)
defer stop()

// we should wait until all services will gracefully stopped
Expand Down
31 changes: 31 additions & 0 deletions group/group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,37 @@ func TestNew(t *testing.T) {
})
}

{ // should stop all services when one is failed
ctx, cancel := context.WithCancel(context.Background())
cases = append(cases, testCase{
name: "should stop all services when one is failed",

ctx: ctx,
cancel: cancel,

await: defaultAwait,

shutdown: time.Nanosecond,
expect: errAlways,
services: []service{
{
shutdown: func(ctx context.Context) { <-ctx.Done() },
callback: func(context.Context) error { return errAlways },
},

{
shutdown: func(ctx context.Context) { <-ctx.Done() },
callback: func(ctx context.Context) error {
// should not freeze
<-ctx.Done()

return ctx.Err()
},
},
},
})
}

{ // errored service
ctx, cancel := context.WithCancel(context.Background())
cases = append(cases, testCase{
Expand Down

0 comments on commit ec311ad

Please sign in to comment.