3737import java .util .Set ;
3838import java .util .concurrent .ConcurrentHashMap ;
3939import java .util .concurrent .atomic .AtomicBoolean ;
40+ import java .util .function .Supplier ;
4041
4142public class SubscriptionBrokerAgent {
4243
@@ -45,6 +46,9 @@ public class SubscriptionBrokerAgent {
4546 private final Map <String , SubscriptionBroker > consumerGroupIdToSubscriptionBroker =
4647 new ConcurrentHashMap <>();
4748
49+ private final Cache <Integer > prefetchingQueueCount =
50+ new Cache <>(this ::getPrefetchingQueueCountInternal );
51+
4852 //////////////////////////// provided for subscription agent ////////////////////////////
4953
5054 public List <SubscriptionEvent > poll (
@@ -193,6 +197,7 @@ public void bindPrefetchingQueue(final SubscriptionConnectorSubtask subtask) {
193197 return broker ;
194198 })
195199 .bindPrefetchingQueue (subtask .getTopicName (), subtask .getInputPendingQueue ());
200+ prefetchingQueueCount .invalidate ();
196201 }
197202
198203 public void updateCompletedTopicNames (final String consumerGroupId , final String topicName ) {
@@ -213,6 +218,7 @@ public void unbindPrefetchingQueue(final String consumerGroupId, final String to
213218 return ;
214219 }
215220 broker .unbindPrefetchingQueue (topicName );
221+ prefetchingQueueCount .invalidate ();
216222 }
217223
218224 public void removePrefetchingQueue (final String consumerGroupId , final String topicName ) {
@@ -223,6 +229,7 @@ public void removePrefetchingQueue(final String consumerGroupId, final String to
223229 return ;
224230 }
225231 broker .removePrefetchingQueue (topicName );
232+ prefetchingQueueCount .invalidate ();
226233 }
227234
228235 public boolean executePrefetch (final String consumerGroupId , final String topicName ) {
@@ -251,8 +258,56 @@ public int getPipeEventCount(final String consumerGroupId, final String topicNam
251258 }
252259
253260 public int getPrefetchingQueueCount () {
261+ return prefetchingQueueCount .get ();
262+ }
263+
264+ private int getPrefetchingQueueCountInternal () {
254265 return consumerGroupIdToSubscriptionBroker .values ().stream ()
255266 .map (SubscriptionBroker ::getPrefetchingQueueCount )
256267 .reduce (0 , Integer ::sum );
257268 }
269+
270+ /////////////////////////////// Cache ///////////////////////////////
271+
272+ /**
273+ * A simple generic cache that computes and stores a value on demand.
274+ *
275+ * <p>Note that since the get() and invalidate() methods are not modified with synchronized, the
276+ * value obtained may not be entirely accurate.
277+ *
278+ * @param <T> the type of the cached value
279+ */
280+ private static class Cache <T > {
281+
282+ private T value ;
283+ private volatile boolean valid = false ;
284+ private final Supplier <T > supplier ;
285+
286+ /**
287+ * Construct a cache with a supplier that knows how to compute the value.
288+ *
289+ * @param supplier a Supplier that computes the value when needed
290+ */
291+ private Cache (final Supplier <T > supplier ) {
292+ this .supplier = supplier ;
293+ }
294+
295+ /** Invalidate the cache. The next call to get() will recompute the value. */
296+ private void invalidate () {
297+ valid = false ;
298+ }
299+
300+ /**
301+ * Return the cached value, recomputing it if the cache is invalid.
302+ *
303+ * @return the current value, recomputed if necessary
304+ */
305+ private T get () {
306+ if (!valid ) {
307+ value = supplier .get ();
308+ valid = true ;
309+ }
310+ return value ;
311+ }
312+ }
258313}
0 commit comments