11package org .phoebus .channelfinder .configuration ;
22
3+ import jakarta .annotation .PostConstruct ;
4+ import java .time .Instant ;
35import java .util .ArrayList ;
46import java .util .Arrays ;
7+ import java .util .Collections ;
58import java .util .EnumMap ;
69import java .util .HashMap ;
710import java .util .List ;
811import java .util .Map ;
912import java .util .Optional ;
13+ import java .util .concurrent .TimeUnit ;
1014import java .util .logging .Level ;
1115import java .util .logging .Logger ;
1216import java .util .stream .Collectors ;
2024import org .phoebus .channelfinder .service .model .archiver .aa .ArchiveAction ;
2125import org .phoebus .channelfinder .service .model .archiver .aa .ArchivePVOptions ;
2226import org .phoebus .channelfinder .service .model .archiver .aa .ArchiverInfo ;
27+ import org .phoebus .channelfinder .service .model .archiver .aa .ArchiverPolicies ;
2328import org .springframework .beans .factory .annotation .Autowired ;
2429import org .springframework .beans .factory .annotation .Value ;
2530import org .springframework .boot .autoconfigure .condition .ConditionalOnProperty ;
2631import org .springframework .context .annotation .Configuration ;
32+ import org .springframework .scheduling .annotation .Scheduled ;
2733import tools .jackson .core .JacksonException ;
2834
2935/**
@@ -70,6 +76,12 @@ public class AAChannelProcessor implements ChannelProcessor {
7076
7177 @ Autowired private ArchiverService archiverService ;
7278
79+ @ Value ("${aa.policy_refresh_interval_seconds:3600}" )
80+ private long policyRefreshIntervalSeconds ;
81+
82+ private volatile Map <String , ArchiverPolicies > cachedPolicies = Map .of ();
83+ private volatile Instant lastPolicyRefresh ;
84+
7385 @ Override
7486 public boolean enabled () {
7587 return aaEnabled ;
@@ -80,8 +92,24 @@ public void setEnabled(boolean enabled) {
8092 this .aaEnabled = enabled ;
8193 }
8294
95+ @ PostConstruct
96+ public void initPolicyCache () {
97+ refreshPolicies ();
98+ }
99+
100+ @ Scheduled (
101+ fixedDelayString = "${aa.policy_refresh_interval_seconds:3600}" ,
102+ timeUnit = TimeUnit .SECONDS )
103+ public void scheduledPolicyRefresh () {
104+ refreshPolicies ();
105+ }
106+
83107 @ Override
84108 public ChannelProcessorInfo processorInfo () {
109+ String policyCounts =
110+ cachedPolicies .entrySet ().stream ()
111+ .map (e -> e .getKey () + "=" + e .getValue ())
112+ .collect (Collectors .joining (", " ));
85113 return new ChannelProcessorInfo (
86114 "AAChannelProcessor" ,
87115 aaEnabled ,
@@ -93,7 +121,15 @@ public ChannelProcessorInfo processorInfo() {
93121 "Archivers" ,
94122 aaURLs .keySet ().toString (),
95123 "AutoPauseOn" ,
96- autoPauseOptions .toString ()));
124+ autoPauseOptions .toString (),
125+ "PostSupportArchivers" ,
126+ postSupportArchivers .toString (),
127+ "PolicyRefreshIntervalSeconds" ,
128+ String .valueOf (policyRefreshIntervalSeconds ),
129+ "LastPolicyRefresh" ,
130+ lastPolicyRefresh == null ? "never" : lastPolicyRefresh .toString (),
131+ "CachedPoliciesPerArchiver" ,
132+ policyCounts .isEmpty () ? "none" : policyCounts ));
97133 }
98134
99135 /**
@@ -112,7 +148,7 @@ public long process(List<Channel> channels) throws JacksonException {
112148 return 0 ;
113149 }
114150
115- Map <String , ArchiverInfo > archiversInfo = getArchiversInfo ( aaURLs );
151+ Map <String , ArchiverInfo > archiversInfo = getArchiversInfoFromCache ( );
116152 if (archiversInfo .isEmpty ()) {
117153 logger .log (
118154 Level .WARNING ,
@@ -271,10 +307,6 @@ private ArchiveAction pickArchiveAction(String archiveStatus, String pvStatus) {
271307
272308 private Optional <Map <ArchiveAction , List <ArchivePVOptions >>> getArchiveActions (
273309 Map <String , ArchivePVOptions > archivePVS , ArchiverInfo archiverInfo ) {
274- if (archiverInfo == null ) {
275- return Optional .of (Map .of ());
276- }
277-
278310 logger .log (
279311 Level .FINE ,
280312 () ->
@@ -358,14 +390,71 @@ private ArchivePVOptions createArchivePV(
358390 return newArchiverPV ;
359391 }
360392
361- private Map <String , ArchiverInfo > getArchiversInfo (Map <String , String > aaURLs ) {
393+ private Map <String , ArchiverInfo > getArchiversInfoFromCache () {
394+ Map <String , ArchiverPolicies > snapshot = cachedPolicies ;
362395 return aaURLs .entrySet ().stream ()
363- .filter (aa -> !StringUtils .isEmpty (aa .getValue ()))
396+ .filter (e -> !StringUtils .isEmpty (e .getValue ()))
397+ .filter (
398+ e -> {
399+ if (!snapshot .containsKey (e .getKey ())) {
400+ logger .log (
401+ Level .WARNING ,
402+ () ->
403+ String .format (
404+ "Archiver '%s' has no cached policies (unreachable at last refresh); skipping." ,
405+ e .getKey ()));
406+ return false ;
407+ }
408+ return true ;
409+ })
364410 .collect (
365411 Collectors .toMap (
366412 Map .Entry ::getKey ,
367- aa ->
413+ e ->
368414 new ArchiverInfo (
369- aa .getKey (), aa .getValue (), archiverService .getAAPolicies (aa .getValue ()))));
415+ e .getKey (), e .getValue (), snapshot .get (e .getKey ()).policies ())));
416+ }
417+
418+ private void refreshPolicies () {
419+ if (aaURLs .isEmpty ()) {
420+ logger .log (Level .FINE , "No archivers configured; skipping policy cache refresh." );
421+ return ;
422+ }
423+ Map <String , ArchiverPolicies > current = cachedPolicies ;
424+ Map <String , ArchiverPolicies > updated = new HashMap <>(current );
425+ List <String > changed = new ArrayList <>();
426+
427+ for (Map .Entry <String , String > entry : aaURLs .entrySet ()) {
428+ if (StringUtils .isEmpty (entry .getValue ())) continue ;
429+ String alias = entry .getKey ();
430+ try {
431+ List <String > fresh = archiverService .getAAPolicies (entry .getValue ());
432+ ArchiverPolicies existing = current .get (alias );
433+ if (existing == null || !existing .policies ().equals (fresh )) {
434+ updated .put (alias , new ArchiverPolicies (fresh ));
435+ changed .add (alias );
436+ }
437+ } catch (ArchiverServiceException ex ) {
438+ logger .log (
439+ Level .WARNING ,
440+ () ->
441+ String .format (
442+ "Policy fetch failed for archiver '%s'; retaining cached policies: %s" ,
443+ alias , ex .getMessage ()));
444+ }
445+ }
446+
447+ lastPolicyRefresh = Instant .now ();
448+ if (!changed .isEmpty ()) {
449+ cachedPolicies = Collections .unmodifiableMap (updated );
450+ logger .log (
451+ Level .INFO ,
452+ "AA policy cache updated: {0}" ,
453+ cachedPolicies .entrySet ().stream ()
454+ .map (e -> e .getKey () + "=" + e .getValue ())
455+ .collect (Collectors .joining (", " )));
456+ } else {
457+ logger .log (Level .FINE , "AA policy cache unchanged after refresh." );
458+ }
370459 }
371460}
0 commit comments