@Test public void testExpire() throws Exception { DefaultHeaderChannelRegistry registry = new DefaultHeaderChannelRegistry(50); registry.setTaskScheduler(this.taskScheduler); String id = (String) registry.channelToChannelName(new DirectChannel()); int n = 0; while (n++ < 100 && registry.channelNameToChannel(id) != null) { Thread.sleep(100); } assertNull(registry.channelNameToChannel(id)); registry.stop(); }
@Override @Nullable public Object channelToChannelName(@Nullable Object channel, long timeToLive) { if (!this.running && !this.explicitlyStopped && this.getTaskScheduler() != null) { start(); } if (channel instanceof MessageChannel) { String name = this.uuid + id.incrementAndGet(); this.channels.put(name, new MessageChannelWrapper((MessageChannel) channel, System.currentTimeMillis() + timeToLive)); if (logger.isDebugEnabled()) { logger.debug("Registered " + channel + " as " + name); } return name; } else { return channel; } }
/** * Cancel the scheduled reap task and run immediately; then reschedule. */ @Override public synchronized void runReaper() { if (this.reaperScheduledFuture != null) { this.reaperScheduledFuture.cancel(true); this.reaperScheduledFuture = null; } run(); }
@Test public void testRemoveOnGet() { DefaultHeaderChannelRegistry registry = new DefaultHeaderChannelRegistry(); MessageChannel channel = new DirectChannel(); String foo = (String) registry.channelToChannelName(channel); Map<?, ?> map = TestUtils.getPropertyValue(registry, "channels", Map.class); assertEquals(1, map.size()); assertSame(channel, registry.channelNameToChannel(foo)); assertEquals(1, map.size()); registry.setRemoveOnGet(true); assertSame(channel, registry.channelNameToChannel(foo)); assertEquals(0, map.size()); }
@Override @Nullable public Object channelToChannelName(@Nullable Object channel) { return channelToChannelName(channel, this.reaperDelay); }
@Override public synchronized void start() { if (!this.running) { Assert.notNull(getTaskScheduler(), "a task scheduler is required"); this.reaperScheduledFuture = getTaskScheduler() .schedule(this, new Date(System.currentTimeMillis() + this.reaperDelay)); this.running = true; } }
public void stop(Runnable callback) { stop(); callback.run(); }
/** * Constructs a registry with the provided delay (milliseconds) for * channel expiry. * @param reaperDelay the delay in milliseconds. */ public DefaultHeaderChannelRegistry(long reaperDelay) { this.setReaperDelay(reaperDelay); }
@Override public Object channelToChannelName(@Nullable Object channel) { return channelToChannelName(channel, this.reaperDelay); }
@Override protected void onInit() { super.onInit(); Assert.notNull(getTaskScheduler(), "a task scheduler is required"); }
public void stop(Runnable callback) { stop(); callback.run(); }
/** * Constructs a registry with the provided delay (milliseconds) for * channel expiry. * @param reaperDelay the delay in milliseconds. */ public DefaultHeaderChannelRegistry(long reaperDelay) { this.setReaperDelay(reaperDelay); }
@Override public Object channelToChannelName(@Nullable Object channel, long timeToLive) { if (!this.running && !this.explicitlyStopped && this.getTaskScheduler() != null) { start(); } if (channel != null && channel instanceof MessageChannel) { String name = this.uuid + id.incrementAndGet(); this.channels.put(name, new MessageChannelWrapper((MessageChannel) channel, System.currentTimeMillis() + timeToLive)); if (logger.isDebugEnabled()) { logger.debug("Registered " + channel + " as " + name); } return name; } else { return channel; } }
@Test public void testControlHeaderChannelReaper() throws InterruptedException { MessagingTemplate messagingTemplate = new MessagingTemplate(); messagingTemplate.convertAndSend(input, "@integrationHeaderChannelRegistry.size()"); Message<?> result = this.output.receive(0); assertNotNull(result); // No channels in the registry assertEquals(0, result.getPayload()); this.registry.channelToChannelName(new DirectChannel()); // Sleep a bit to be sure that we aren't reaped by registry TTL as 60000 Thread.sleep(10); messagingTemplate.convertAndSend(input, "@integrationHeaderChannelRegistry.size()"); result = this.output.receive(0); assertNotNull(result); assertEquals(1, result.getPayload()); // Some DirectFieldAccessor magic to modify 'expireAt' to the past to avoid timing issues on high-loaded build Object messageChannelWrapper = TestUtils.getPropertyValue(this.registry, "channels", Map.class).values().iterator().next(); DirectFieldAccessor dfa = new DirectFieldAccessor(messageChannelWrapper); dfa.setPropertyValue("expireAt", System.currentTimeMillis() - 60000); messagingTemplate.convertAndSend(input, "@integrationHeaderChannelRegistry.runReaper()"); messagingTemplate.convertAndSend(input, "@integrationHeaderChannelRegistry.size()"); result = this.output.receive(0); assertNotNull(result); assertEquals(0, result.getPayload()); }
@Override public synchronized void run() { if (logger.isTraceEnabled()) { logger.trace("Reaper started; channels size=" + this.channels.size()); } Iterator<Entry<String, MessageChannelWrapper>> iterator = this.channels.entrySet().iterator(); long now = System.currentTimeMillis(); while (iterator.hasNext()) { Entry<String, MessageChannelWrapper> entry = iterator.next(); if (entry.getValue().getExpireAt() < now) { if (logger.isDebugEnabled()) { logger.debug("Expiring " + entry.getKey() + " (" + entry.getValue().getChannel() + ")"); } iterator.remove(); } } this.reaperScheduledFuture = getTaskScheduler() .schedule(this, new Date(System.currentTimeMillis() + this.reaperDelay)); if (logger.isTraceEnabled()) { logger.trace("Reaper completed; channels size=" + this.channels.size()); } }
/** * Cancel the scheduled reap task and run immediately; then reschedule. */ @Override public synchronized void runReaper() { if (this.reaperScheduledFuture != null) { this.reaperScheduledFuture.cancel(true); this.reaperScheduledFuture = null; } run(); }
@Override public synchronized void start() { if (!this.running) { Assert.notNull(getTaskScheduler(), "a task scheduler is required"); this.reaperScheduledFuture = getTaskScheduler() .schedule(this, new Date(System.currentTimeMillis() + this.reaperDelay)); this.running = true; } }
@Override protected void onInit() { super.onInit(); Assert.notNull(getTaskScheduler(), "a task scheduler is required"); }
@Override public synchronized void run() { if (logger.isTraceEnabled()) { logger.trace("Reaper started; channels size=" + this.channels.size()); } Iterator<Entry<String, MessageChannelWrapper>> iterator = this.channels.entrySet().iterator(); long now = System.currentTimeMillis(); while (iterator.hasNext()) { Entry<String, MessageChannelWrapper> entry = iterator.next(); if (entry.getValue().getExpireAt() < now) { if (logger.isDebugEnabled()) { logger.debug("Expiring " + entry.getKey() + " (" + entry.getValue().getChannel() + ")"); } iterator.remove(); } } this.reaperScheduledFuture = getTaskScheduler() .schedule(this, new Date(System.currentTimeMillis() + this.reaperDelay)); if (logger.isTraceEnabled()) { logger.trace("Reaper completed; channels size=" + this.channels.size()); } }