-
-
Notifications
You must be signed in to change notification settings - Fork 108
Expand file tree
/
Copy pathdi_lifecycle.go
More file actions
396 lines (377 loc) · 12.9 KB
/
di_lifecycle.go
File metadata and controls
396 lines (377 loc) · 12.9 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
package do
import "context"
// Healthchecker is an interface that services can implement to provide health checking capabilities.
// Services implementing this interface can be health-checked by the DI container to ensure they
// are functioning correctly.
//
// The HealthCheck method should perform a quick check to verify the service is healthy.
// It should return nil if the service is healthy, or an error describing the health issue.
//
// Example:
//
// type Database struct {
// conn *sql.DB
// }
//
// func (db *Database) HealthCheck() error {
// return db.conn.Ping()
// }
type Healthchecker interface {
HealthCheck() error
}
// HealthcheckerWithContext is an interface that services can implement to provide health checking
// capabilities with context support. This allows for timeout and cancellation control during
// health checks.
//
// The HealthCheck method should perform a quick check to verify the service is healthy.
// It should respect the provided context for cancellation and timeout.
// It should return nil if the service is healthy, or an error describing the health issue.
//
// Example:
//
// type Database struct {
// conn *sql.DB
// }
//
// func (db *Database) HealthCheck(ctx context.Context) error {
// return db.conn.PingContext(ctx)
// }
type HealthcheckerWithContext interface {
HealthCheck(context.Context) error
}
// Shutdowner is an interface that services can implement to provide graceful shutdown capabilities.
// Services implementing this interface will be called during container shutdown to perform
// cleanup operations.
//
// The Shutdown method should perform any necessary cleanup, such as closing connections,
// flushing buffers, or stopping background processes.
//
// Example:
//
// type Logger struct {
// file *os.File
// }
//
// func (l *Logger) Shutdown() {
// l.file.Close()
// }
type Shutdowner interface {
Shutdown()
}
// ShutdownerWithError is an interface that services can implement to provide graceful shutdown
// capabilities with error reporting. This allows services to report any errors that occur
// during shutdown.
//
// The Shutdown method should perform any necessary cleanup and return an error if the
// shutdown process fails.
//
// Example:
//
// type Database struct {
// conn *sql.DB
// }
//
// func (db *Database) Shutdown() error {
// return db.conn.Close()
// }
type ShutdownerWithError interface {
Shutdown() error
}
// ShutdownerWithContext is an interface that services can implement to provide graceful shutdown
// capabilities with context support. This allows for timeout and cancellation control during
// shutdown operations.
//
// The Shutdown method should perform any necessary cleanup and respect the provided context
// for cancellation and timeout.
//
// Example:
//
// type Server struct {
// srv *http.Server
// }
//
// func (s *Server) Shutdown(ctx context.Context) {
// s.srv.Shutdown(ctx)
// }
type ShutdownerWithContext interface {
Shutdown(context.Context)
}
// ShutdownerWithContextAndError is an interface that services can implement to provide graceful
// shutdown capabilities with both context support and error reporting. This is the most flexible
// shutdown interface, allowing for timeout control and error reporting.
//
// The Shutdown method should perform any necessary cleanup, respect the provided context
// for cancellation and timeout, and return an error if the shutdown process fails.
//
// Example:
//
// type Server struct {
// srv *http.Server
// }
//
// func (s *Server) Shutdown(ctx context.Context) error {
// return s.srv.Shutdown(ctx)
// }
type ShutdownerWithContextAndError interface {
Shutdown(context.Context) error
}
// HealthCheck returns a service status, using type inference to determine the service name.
// This function performs a health check on a service by inferring its name from the type T.
// The service must implement either Healthchecker or HealthcheckerWithContext interface.
//
// Parameters:
// - i: The injector containing the service
//
// Returns an error if the health check fails, or nil if the service is healthy.
//
// Play: https://go.dev/play/p/dg1OzQCFJVm
//
// Example:
//
// err := do.HealthCheck[*Database](injector)
// if err != nil {
// log.Printf("Database health check failed: %v", err)
// }
func HealthCheck[T any](i Injector) error {
name := inferServiceName[T]()
return HealthCheckNamedWithContext(context.Background(), i, name)
}
// HealthCheckWithContext returns a service status, using type inference to determine the service name.
// This function performs a health check on a service with context support for timeout and cancellation.
// The service must implement either Healthchecker or HealthcheckerWithContext interface.
//
// Parameters:
// - ctx: Context for cancellation and timeout control
// - i: The injector containing the service
//
// Returns an error if the health check fails, or nil if the service is healthy.
//
// Play: https://go.dev/play/p/jhaaEIPad_d
//
// Example:
//
// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
// defer cancel()
//
// err := do.HealthCheckWithContext[*Database](ctx, injector)
// if err != nil {
// log.Printf("Database health check failed: %v", err)
// }
func HealthCheckWithContext[T any](ctx context.Context, i Injector) error {
name := inferServiceName[T]()
return HealthCheckNamedWithContext(ctx, i, name)
}
// HealthCheckNamed returns a service status for a named service.
// This function performs a health check on a service with the specified name.
// The service must implement either Healthchecker or HealthcheckerWithContext interface.
//
// Parameters:
// - i: The injector containing the service
// - name: The name of the service to health check
//
// Returns an error if the health check fails, or nil if the service is healthy.
//
// Play: https://go.dev/play/p/jhaaEIPad_d
//
// Example:
//
// err := do.HealthCheckNamed(injector, "main-database")
// if err != nil {
// log.Printf("Main database health check failed: %v", err)
// }
func HealthCheckNamed(i Injector, name string) error {
return HealthCheckNamedWithContext(context.Background(), i, name)
}
// HealthCheckNamedWithContext returns a service status for a named service with context support.
// This function performs a health check on a service with the specified name and context support
// for timeout and cancellation. The service must implement either Healthchecker or
// HealthcheckerWithContext interface.
//
// Parameters:
// - ctx: Context for cancellation and timeout control
// - i: The injector containing the service
// - name: The name of the service to health check
//
// Returns an error if the health check fails, or nil if the service is healthy.
//
// Example:
//
// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
// defer cancel()
//
// err := do.HealthCheckNamedWithContext(ctx, injector, "main-database")
// if err != nil {
// log.Printf("Main database health check failed: %v", err)
// }
func HealthCheckNamedWithContext(ctx context.Context, i Injector, name string) error {
// @TODO: should we queue the health check into the healthcheck pool ?
return getInjectorOrDefault(i).serviceHealthCheck(ctx, name)
}
// Shutdown stops a service, using type inference to determine the service name.
// This function performs a graceful shutdown on a service by inferring its name from the type T.
// The service must implement one of the Shutdowner interfaces.
//
// Parameters:
// - i: The injector containing the service
//
// Returns an error if the shutdown fails, or nil if the shutdown was successful.
//
// Play: https://go.dev/play/p/uOvsiVWa9_R
//
// Example:
//
// err := do.Shutdown[*Database](injector)
// if err != nil {
// log.Printf("Database shutdown failed: %v", err)
// }
func Shutdown[T any](i Injector) error {
name := inferServiceName[T]()
return ShutdownNamedWithContext(context.Background(), i, name)
}
// ShutdownWithContext stops a service, using type inference to determine the service name.
// This function performs a graceful shutdown on a service with context support for timeout
// and cancellation. The service must implement one of the Shutdowner interfaces.
//
// Parameters:
// - ctx: Context for cancellation and timeout control
// - i: The injector containing the service
//
// Returns an error if the shutdown fails, or nil if the shutdown was successful.
//
// Play: https://go.dev/play/p/qAaIo5dWz7J
//
// Example:
//
// ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
// defer cancel()
//
// err := do.ShutdownWithContext[*Database](ctx, injector)
// if err != nil {
// log.Printf("Database shutdown failed: %v", err)
// }
func ShutdownWithContext[T any](ctx context.Context, i Injector) error {
name := inferServiceName[T]()
return ShutdownNamedWithContext(ctx, i, name)
}
// ShutdownNamed stops a named service.
// This function performs a graceful shutdown on a service with the specified name.
// The service must implement one of the Shutdowner interfaces.
//
// Parameters:
// - i: The injector containing the service
// - name: The name of the service to shutdown
//
// Returns an error if the shutdown fails, or nil if the shutdown was successful.
//
// Play: https://go.dev/play/p/qAaIo5dWz7J
//
// Example:
//
// err := do.ShutdownNamed(injector, "main-database")
// if err != nil {
// log.Printf("Main database shutdown failed: %v", err)
// }
func ShutdownNamed(i Injector, name string) error {
return ShutdownNamedWithContext(context.Background(), i, name)
}
// ShutdownNamedWithContext stops a named service with context support.
// This function performs a graceful shutdown on a service with the specified name and context
// support for timeout and cancellation. The service must implement one of the Shutdowner interfaces.
//
// Parameters:
// - ctx: Context for cancellation and timeout control
// - i: The injector containing the service
// - name: The name of the service to shutdown
//
// Returns an error if the shutdown fails, or nil if the shutdown was successful.
//
// Example:
//
// ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
// defer cancel()
//
// err := do.ShutdownNamedWithContext(ctx, injector, "main-database")
// if err != nil {
// log.Printf("Main database shutdown failed: %v", err)
// }
func ShutdownNamedWithContext(ctx context.Context, i Injector, name string) error {
return getInjectorOrDefault(i).serviceShutdown(ctx, name)
}
// MustShutdown stops a service, using type inference to determine the service name. It panics on error.
// This function performs a graceful shutdown on a service by inferring its name from the type T.
// If the shutdown fails, this function will panic.
//
// Parameters:
// - i: The injector containing the service
//
// Panics if the shutdown fails.
//
// Play: https://go.dev/play/p/cjKFvjZpeAV
//
// Example:
//
// do.MustShutdown[*Database](injector)
func MustShutdown[T any](i Injector) {
must0(Shutdown[T](i))
}
// MustShutdownWithContext stops a service, using type inference to determine the service name. It panics on error.
// This function performs a graceful shutdown on a service with context support for timeout
// and cancellation. If the shutdown fails, this function will panic.
//
// Parameters:
// - ctx: Context for cancellation and timeout control
// - i: The injector containing the service
//
// Panics if the shutdown fails.
//
// Play: https://go.dev/play/p/cjKFvjZpeAV
//
// Example:
//
// ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
// defer cancel()
//
// do.MustShutdownWithContext[*Database](ctx, injector)
func MustShutdownWithContext[T any](ctx context.Context, i Injector) {
must0(ShutdownWithContext[T](ctx, i))
}
// MustShutdownNamed stops a named service. It panics on error.
// This function performs a graceful shutdown on a service with the specified name.
// If the shutdown fails, this function will panic.
//
// Parameters:
// - i: The injector containing the service
// - name: The name of the service to shutdown
//
// Panics if the shutdown fails.
//
// Play: https://go.dev/play/p/cjKFvjZpeAV
//
// Example:
//
// do.MustShutdownNamed(injector, "main-database")
func MustShutdownNamed(i Injector, name string) {
must0(ShutdownNamed(i, name))
}
// MustShutdownNamedWithContext stops a named service. It panics on error.
// This function performs a graceful shutdown on a service with the specified name and context
// support for timeout and cancellation. If the shutdown fails, this function will panic.
//
// Parameters:
// - ctx: Context for cancellation and timeout control
// - i: The injector containing the service
// - name: The name of the service to shutdown
//
// Panics if the shutdown fails.
//
// Play: https://go.dev/play/p/cjKFvjZpeAV
//
// Example:
//
// ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
// defer cancel()
//
// do.MustShutdownNamedWithContext(ctx, injector, "main-database")
func MustShutdownNamedWithContext(ctx context.Context, i Injector, name string) {
must0(ShutdownNamedWithContext(ctx, i, name))
}