11//
22// DISCLAIMER
33//
4- // Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
4+ // Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
55//
66// Licensed under the Apache License, Version 2.0 (the "License");
77// you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ package agency
2323import (
2424 "context"
2525 "sync"
26+ "time"
2627
2728 "github.com/rs/zerolog"
2829
@@ -157,6 +158,8 @@ type Cache interface {
157158 CommitIndex () uint64
158159 // Health returns true when healthy object is available.
159160 Health () (Health , bool )
161+ // ShardsInSyncMap returns last in sync state of particular shard
162+ ShardsInSyncMap () (ShardsSyncStatus , bool )
160163}
161164
162165func NewCache (namespace , name string , mode * api.DeploymentMode ) Cache {
@@ -169,8 +172,9 @@ func NewCache(namespace, name string, mode *api.DeploymentMode) Cache {
169172
170173func NewAgencyCache (namespace , name string ) Cache {
171174 c := & cache {
172- namespace : namespace ,
173- name : name ,
175+ namespace : namespace ,
176+ name : name ,
177+ shardsSyncStatus : ShardsSyncStatus {},
174178 }
175179
176180 c .log = logger .WrapObj (c )
@@ -185,6 +189,10 @@ func NewSingleCache() Cache {
185189type cacheSingle struct {
186190}
187191
192+ func (c cacheSingle ) ShardsInSyncMap () (ShardsSyncStatus , bool ) {
193+ return nil , false
194+ }
195+
188196func (c cacheSingle ) DataDB () (StateDB , bool ) {
189197 return StateDB {}, false
190198}
@@ -221,6 +229,8 @@ type cache struct {
221229 dataDB StateDB
222230
223231 health Health
232+
233+ shardsSyncStatus ShardsSyncStatus
224234}
225235
226236func (c * cache ) WrapLogger (in * zerolog.Event ) * zerolog.Event {
@@ -272,6 +282,38 @@ func (c *cache) Reload(ctx context.Context, size int, clients map[string]agency.
272282 c .lock .Lock ()
273283 defer c .lock .Unlock ()
274284
285+ index , err := c .reload (ctx , size , clients )
286+ if err != nil {
287+ return index , err
288+ }
289+
290+ if ! c .valid {
291+ return index , nil
292+ }
293+
294+ // Refresh map of the shards
295+ shardNames := c .data .GetShardsStatus ()
296+
297+ n := time .Now ()
298+
299+ for k := range c .shardsSyncStatus {
300+ if _ , ok := shardNames [k ]; ! ok {
301+ delete (c .shardsSyncStatus , k )
302+ }
303+ }
304+
305+ for k , v := range shardNames {
306+ if _ , ok := c .shardsSyncStatus [k ]; ! ok {
307+ c .shardsSyncStatus [k ] = n
308+ } else if v {
309+ c .shardsSyncStatus [k ] = n
310+ }
311+ }
312+
313+ return index , nil
314+ }
315+
316+ func (c * cache ) reload (ctx context.Context , size int , clients map [string ]agency.Agency ) (uint64 , error ) {
275317 leaderCli , leaderConfig , health , err := c .getLeader (ctx , size , clients )
276318 if err != nil {
277319 // Invalidate a leader ID and agency state.
@@ -304,6 +346,21 @@ func (c *cache) Reload(ctx context.Context, size int, clients map[string]agency.
304346 }
305347}
306348
349+ func (c * cache ) ShardsInSyncMap () (ShardsSyncStatus , bool ) {
350+ c .lock .RLock ()
351+ defer c .lock .RUnlock ()
352+
353+ if ! c .valid {
354+ return nil , false
355+ }
356+
357+ if c .shardsSyncStatus == nil {
358+ return nil , false
359+ }
360+
361+ return c .shardsSyncStatus , true
362+ }
363+
307364// getLeader returns config and client to a leader agency, and health to check if agencies are on the same page.
308365// If there is no quorum for the leader then error is returned.
309366func (c * cache ) getLeader (ctx context.Context , size int , clients map [string ]agency.Agency ) (agency.Agency , * Config , health , error ) {
0 commit comments