aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 0ada43facb36ac63630ad5f57d983f879b0fbc92 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# rutina

Package Rutina (russian "рутина" - ordinary boring everyday work) is routine orchestrator for your application.

It seems like https://godoc.org/golang.org/x/sync/errgroup with some different:

1) propagates context to every routines. So routine can check if context stopped (`ctx.Done()`).
2) has flexible run/stop policy. i.e. one routine restarts when it fails (useful on daemons) but if fails another - all routines will be cancelled 
3) already has optional signal handler `ListenOsSignals()`

## When it need?

Usually, when your program consists of several routines (i.e.: http server, metrics server and os signals subscriber) and you want to stop all routines when one of them ends (i.e.: by TERM os signal in signal subscriber).

## Usage

### New instance

```go
r := rutina.New()
```

or with optional mixins (see below):

```go
r := rutina.New(...Mixins)
```
or
```go 
r.With(...Mixins)
```

### Start new routine

```go
r.Go(func (ctx context.Context) error {
    ...do something...
}, ...runOptions)
```

Available options of run policy:

* `ShutdownIfFail` - Shutdown all routines if this routine fails
* `RestartIfFail` - Restart this routine if it fail
* `DoNothingIfFail` - Do nothing just stop this routine if it fail
* `ShutdownIfDone` - Shutdown all routines if this routine done without errors
* `RestartIfDone` - Restart if this routine done without errors
* `DoNothingIfDone` - Do nothing if this routine done without errors

Default policy:

`ShutdownIfFail` && `DoNothingIfDone` 

#### Example of run policies

```go
    r.Go(func(ctx context.Context) error {
		// If this routine produce no error - it just restarts
		// If it returns error - all other routines will shutdown (because context cancels)
	}, rutina.RestartIfDone, rutina.ShutdownIfFail)

	r.Go(func(ctx context.Context) error {
		// If this routine produce no error - it just completes
		// If it returns error - all other routines will shutdown (because context cancels)
	}, rutina.DoNothingIfDone, rutina.ShutdownIfFail)

	r.Go(func(ctx context.Context) error {
		// If this routine produce no error - all other routines will shutdown (because context cancels)
		// If it returns error - it will be restarted
	}, rutina.RestartIfFail)

	r.Go(func(ctx context.Context) error {
		// If this routine stopped by any case - all other routines will shutdown (because context cancels)
	}, rutina.ShutdownIfDone)

	r.ListenOsSignals() // Shutdown all routines by OS signal
```

### Wait routines to complete

```go
err := r.Wait()
```

Here err = error that shutdowns all routines (may be will be changed at future)

## Mixins

### Usage

```go
r := rutina.New(mixin1, mixin2, ...)
```
or
```go
r := rutina.New()
r = r.With(mixin1, mixin2, ...) // Returns new instance of Rutina!
```

### Logger

```go 
r.With(rutina.WithStdLogger())
``` 
or 
```go 
r.With(rutina.WithLogger(logger log.Logger))
```

Sets standard or custom logger. By default there is no logger.

### Custom context

```go
r.With(rutina.WithContext(ctx context.Context))
````

Propagates your own context to Rutina. By default it use own context. 

## Example

HTTP server with graceful shutdown [`example/http_server.go`](https://github.com/NeonXP/rutina/blob/master/example/http_server.go)

Different run policies [`example/policies.go`](https://github.com/NeonXP/rutina/blob/master/example/policies.go)