@@ -33,23 +33,34 @@ type WatchStopRequest struct {
3333}
3434
3535type WatchStatus struct {
36- Namespace string `json:"namespace,omitempty"`
37- Volume string `json:"volume"`
38- Source SourceRef `json:"source"`
39- Targets []TargetRef `json:"targets"`
40- IncludePaths []string `json:"includePaths,omitempty"`
41- ExcludePaths []string `json:"excludePaths,omitempty"`
42- Running bool `json:"running"`
43- StartedAt time.Time `json:"startedAt"`
44- StoppedAt * time.Time `json:"stoppedAt,omitempty"`
45- LastBatchAt * time.Time `json:"lastBatchAt,omitempty"`
46- LastBatchEventCount int `json:"lastBatchEventCount,omitempty"`
47- LastBatchGeneration string `json:"lastBatchGeneration,omitempty"`
48- LastDeliveryError string `json:"lastDeliveryError,omitempty"`
49- LastWatchError string `json:"lastWatchError,omitempty"`
50- DeliveredBatchCount int64 `json:"deliveredBatchCount,omitempty"`
51- DeliveredEventCount int64 `json:"deliveredEventCount,omitempty"`
52- DeliveryFailureCount int64 `json:"deliveryFailureCount,omitempty"`
36+ Namespace string `json:"namespace,omitempty"`
37+ Volume string `json:"volume"`
38+ Source SourceRef `json:"source"`
39+ Targets []TargetRef `json:"targets"`
40+ TargetStatuses []TargetStatus `json:"targetStatuses,omitempty"`
41+ IncludePaths []string `json:"includePaths,omitempty"`
42+ ExcludePaths []string `json:"excludePaths,omitempty"`
43+ Running bool `json:"running"`
44+ StartedAt time.Time `json:"startedAt"`
45+ StoppedAt * time.Time `json:"stoppedAt,omitempty"`
46+ LastBatchAt * time.Time `json:"lastBatchAt,omitempty"`
47+ LastBatchEventCount int `json:"lastBatchEventCount,omitempty"`
48+ LastBatchGeneration string `json:"lastBatchGeneration,omitempty"`
49+ LastDeliveryError string `json:"lastDeliveryError,omitempty"`
50+ LastWatchError string `json:"lastWatchError,omitempty"`
51+ DeliveredBatchCount int64 `json:"deliveredBatchCount,omitempty"`
52+ DeliveredEventCount int64 `json:"deliveredEventCount,omitempty"`
53+ DeliveryFailureCount int64 `json:"deliveryFailureCount,omitempty"`
54+ }
55+
56+ type TargetStatus struct {
57+ URL string `json:"url"`
58+ LastSuccessfulSync * time.Time `json:"lastSuccessfulSync,omitempty"`
59+ LastObservedGeneration string `json:"lastObservedGeneration,omitempty"`
60+ LastError string `json:"lastError,omitempty"`
61+ DeliveredBatchCount int64 `json:"deliveredBatchCount,omitempty"`
62+ DeliveredEventCount int64 `json:"deliveredEventCount,omitempty"`
63+ DeliveryFailureCount int64 `json:"deliveryFailureCount,omitempty"`
5364}
5465
5566type BatchSender interface {
@@ -139,14 +150,15 @@ func (m *WatchManager) Start(ctx context.Context, req WatchStartRequest) (WatchS
139150 key := watchKey (req .Namespace , req .Volume )
140151 watchCtx , cancel := context .WithCancel (context .Background ())
141152 status := WatchStatus {
142- Namespace : req .Namespace ,
143- Volume : req .Volume ,
144- Source : req .Source ,
145- Targets : append ([]TargetRef (nil ), req .Targets ... ),
146- IncludePaths : append ([]string (nil ), req .IncludePaths ... ),
147- ExcludePaths : append ([]string (nil ), req .ExcludePaths ... ),
148- Running : true ,
149- StartedAt : time .Now ().UTC (),
153+ Namespace : req .Namespace ,
154+ Volume : req .Volume ,
155+ Source : req .Source ,
156+ Targets : append ([]TargetRef (nil ), req .Targets ... ),
157+ TargetStatuses : initialTargetStatuses (req .Targets ),
158+ IncludePaths : append ([]string (nil ), req .IncludePaths ... ),
159+ ExcludePaths : append ([]string (nil ), req .ExcludePaths ... ),
160+ Running : true ,
161+ StartedAt : time .Now ().UTC (),
150162 }
151163
152164 m .mu .Lock ()
@@ -283,17 +295,17 @@ func (m *WatchManager) run(ctx context.Context, key string, watch *managedWatch,
283295 batch .Source = source
284296 for _ , target := range targets {
285297 if err := m .sender .SendBatch (ctx , target , batch ); err != nil {
286- m .recordDeliveryError (key , watch , err )
298+ m .recordDeliveryError (key , watch , target , err )
287299 continue
288300 }
289- m .recordDeliverySuccess (key , watch , batch )
301+ m .recordDeliverySuccess (key , watch , target , batch )
290302 }
291303 return nil
292304 })
293305 m .recordStopped (key , watch , err )
294306}
295307
296- func (m * WatchManager ) recordDeliverySuccess (key string , watch * managedWatch , batch EventBatch ) {
308+ func (m * WatchManager ) recordDeliverySuccess (key string , watch * managedWatch , target TargetRef , batch EventBatch ) {
297309 now := time .Now ().UTC ()
298310 m .mu .Lock ()
299311 defer m .mu .Unlock ()
@@ -306,16 +318,25 @@ func (m *WatchManager) recordDeliverySuccess(key string, watch *managedWatch, ba
306318 watch .status .DeliveredBatchCount ++
307319 watch .status .DeliveredEventCount += int64 (len (batch .Events ))
308320 watch .status .LastDeliveryError = ""
321+ targetStatus := ensureTargetStatus (& watch .status , target .URL )
322+ targetStatus .LastSuccessfulSync = & now
323+ targetStatus .LastObservedGeneration = batch .Generation
324+ targetStatus .DeliveredBatchCount ++
325+ targetStatus .DeliveredEventCount += int64 (len (batch .Events ))
326+ targetStatus .LastError = ""
309327}
310328
311- func (m * WatchManager ) recordDeliveryError (key string , watch * managedWatch , err error ) {
329+ func (m * WatchManager ) recordDeliveryError (key string , watch * managedWatch , target TargetRef , err error ) {
312330 m .mu .Lock ()
313331 defer m .mu .Unlock ()
314332 if m .watches [key ] != watch {
315333 return
316334 }
317335 watch .status .DeliveryFailureCount ++
318336 watch .status .LastDeliveryError = err .Error ()
337+ targetStatus := ensureTargetStatus (& watch .status , target .URL )
338+ targetStatus .DeliveryFailureCount ++
339+ targetStatus .LastError = err .Error ()
319340}
320341
321342func (m * WatchManager ) recordStopped (key string , watch * managedWatch , err error ) {
@@ -350,7 +371,26 @@ func parseOptionalDuration(value string, fallback time.Duration) (time.Duration,
350371
351372func cloneWatchStatus (status WatchStatus ) WatchStatus {
352373 status .Targets = append ([]TargetRef (nil ), status .Targets ... )
374+ status .TargetStatuses = append ([]TargetStatus (nil ), status .TargetStatuses ... )
353375 status .IncludePaths = append ([]string (nil ), status .IncludePaths ... )
354376 status .ExcludePaths = append ([]string (nil ), status .ExcludePaths ... )
355377 return status
356378}
379+
380+ func initialTargetStatuses (targets []TargetRef ) []TargetStatus {
381+ statuses := make ([]TargetStatus , 0 , len (targets ))
382+ for _ , target := range targets {
383+ statuses = append (statuses , TargetStatus {URL : target .URL })
384+ }
385+ return statuses
386+ }
387+
388+ func ensureTargetStatus (status * WatchStatus , targetURL string ) * TargetStatus {
389+ for i := range status .TargetStatuses {
390+ if status .TargetStatuses [i ].URL == targetURL {
391+ return & status .TargetStatuses [i ]
392+ }
393+ }
394+ status .TargetStatuses = append (status .TargetStatuses , TargetStatus {URL : targetURL })
395+ return & status .TargetStatuses [len (status .TargetStatuses )- 1 ]
396+ }
0 commit comments