@@ -34,13 +34,13 @@ import (
34
34
35
35
"github.com/dapr/components-contrib/state"
36
36
actorerrors "github.com/dapr/dapr/pkg/actors/errors"
37
+ "github.com/dapr/dapr/pkg/actors/health"
37
38
"github.com/dapr/dapr/pkg/actors/internal"
38
39
"github.com/dapr/dapr/pkg/actors/timers"
39
40
"github.com/dapr/dapr/pkg/channel"
40
41
configuration "github.com/dapr/dapr/pkg/config"
41
42
diag "github.com/dapr/dapr/pkg/diagnostics"
42
43
diagUtils "github.com/dapr/dapr/pkg/diagnostics/utils"
43
- "github.com/dapr/dapr/pkg/health"
44
44
invokev1 "github.com/dapr/dapr/pkg/messaging/v1"
45
45
"github.com/dapr/dapr/pkg/modes"
46
46
commonv1pb "github.com/dapr/dapr/pkg/proto/common/v1"
@@ -122,6 +122,7 @@ type actorsRuntime struct {
122
122
internalActors map [string ]InternalActor
123
123
internalActorChannel * internalActorChannel
124
124
sec security.Handler
125
+ checker * health.Checker
125
126
wg sync.WaitGroup
126
127
closed atomic.Bool
127
128
closeCh chan struct {}
@@ -178,12 +179,17 @@ func newActorsWithClock(opts ActorsOpts, clock clock.WithTicker) (ActorRuntime,
178
179
179
180
// Init reminders and placement
180
181
providerOpts := internal.ActorsProviderOptions {
181
- Config : a .actorsConfig .Config ,
182
- Security : a .sec ,
183
- AppHealthFn : a .getAppHealthCheckChan ,
184
- Clock : a .clock ,
185
- APILevel : & a .apiLevel ,
186
- Resiliency : a .resiliency ,
182
+ Config : a .actorsConfig .Config ,
183
+ Security : a .sec ,
184
+ AppHealthFn : func (ctx context.Context ) <- chan bool {
185
+ if a .checker == nil {
186
+ return nil
187
+ }
188
+ return a .checker .HealthChannel ()
189
+ },
190
+ Clock : a .clock ,
191
+ APILevel : & a .apiLevel ,
192
+ Resiliency : a .resiliency ,
187
193
}
188
194
189
195
// Initialize the placement client if we don't have a mocked one already
@@ -269,6 +275,19 @@ func (a *actorsRuntime) Init(ctx context.Context) (err error) {
269
275
a .actorsReminders .OnPlacementTablesUpdated (ctx )
270
276
})
271
277
278
+ a .checker , err = a .getAppHealthChecker ()
279
+ if err != nil {
280
+ return fmt .Errorf ("actors: couldn't create health check: %w" , err )
281
+ }
282
+
283
+ if a .checker != nil {
284
+ a .wg .Add (1 )
285
+ go func () {
286
+ defer a .wg .Done ()
287
+ a .checker .Run (ctx )
288
+ }()
289
+ }
290
+
272
291
for _ , actorType := range hat {
273
292
err = a .placement .AddHostedActorType (actorType , a .actorsConfig .GetIdleTimeoutForType (actorType ))
274
293
if err != nil {
@@ -294,26 +313,27 @@ func (a *actorsRuntime) Init(ctx context.Context) (err error) {
294
313
return nil
295
314
}
296
315
297
- func (a * actorsRuntime ) getAppHealthCheckChan ( ctx context. Context ) <- chan bool {
316
+ func (a * actorsRuntime ) getAppHealthChecker () ( * health. Checker , error ) {
298
317
if len (a .actorsConfig .Config .HostedActorTypes .ListActorTypes ()) == 0 || a .appChannel == nil {
299
- return nil
318
+ return nil , nil
300
319
}
301
320
302
321
// Be careful to configure healthz endpoint option. If app healthz returns unhealthy status, Dapr will
303
322
// disconnect from placement to remove the node from consistent hashing ring.
304
323
// i.e if app is busy state, the healthz status would be flaky, which leads to frequent
305
324
// actor rebalancing. It will impact the entire service.
306
- return a .getAppHealthCheckChanWithOptions ( ctx ,
325
+ return a .getAppHealthCheckerWithOptions (
307
326
health .WithFailureThreshold (4 ),
308
- health .WithInterval (5 * time .Second ),
327
+ health .WithHealthyStateInterval (5 * time .Second ),
328
+ health .WithUnHealthyStateInterval (time .Second / 2 ),
309
329
health .WithRequestTimeout (2 * time .Second ),
310
330
health .WithHTTPClient (a .actorsConfig .HealthHTTPClient ),
311
331
)
312
332
}
313
333
314
- func (a * actorsRuntime ) getAppHealthCheckChanWithOptions ( ctx context. Context , opts ... health.Option ) <- chan bool {
334
+ func (a * actorsRuntime ) getAppHealthCheckerWithOptions ( opts ... health.Option ) ( * health. Checker , error ) {
315
335
opts = append (opts , health .WithAddress (a .actorsConfig .HealthEndpoint + "/healthz" ))
316
- return health .StartEndpointHealthCheck ( ctx , opts ... )
336
+ return health .New ( opts ... )
317
337
}
318
338
319
339
func constructCompositeKey (keys ... string ) string {
@@ -1100,19 +1120,20 @@ func isInternalActor(actorType string) bool {
1100
1120
func (a * actorsRuntime ) Close () error {
1101
1121
defer a .wg .Wait ()
1102
1122
1123
+ var errs []error
1103
1124
if a .closed .CompareAndSwap (false , true ) {
1104
- defer close (a .closeCh )
1105
- errs := []error {}
1125
+ defer func () { close (a .closeCh ) }()
1126
+ if a .checker != nil {
1127
+ a .checker .Close ()
1128
+ }
1106
1129
if a .placement != nil {
1107
- err := a .placement .Close ()
1108
- if err != nil {
1130
+ if err := a .placement .Close (); err != nil {
1109
1131
errs = append (errs , fmt .Errorf ("failed to close placement service: %w" , err ))
1110
1132
}
1111
1133
}
1112
- return errors .Join (errs ... )
1113
1134
}
1114
1135
1115
- return nil
1136
+ return errors . Join ( errs ... )
1116
1137
}
1117
1138
1118
1139
// ValidateHostEnvironment validates that actors can be initialized properly given a set of parameters
0 commit comments