public static TimerPushService get(final Application application) { TimerPushService service = INSTANCES.get(application); if (service == null) { service = new TimerPushService(); final TimerPushService existingInstance = INSTANCES.putIfAbsent(application, service); if (existingInstance == null) /* * If this is the first instance of this service for the given application, then * schedule the cleanup task. */ service.setCleanupInterval(Duration.seconds(60)); else // If it is not the first instance, throw it away. service = existingInstance; } return service; }
@Override protected TimerPushService lookupService() { return TimerPushService.get(); } };
/** * {@inheritDoc} */ public <EventType> TimerPushNode<EventType> installNode(final Component component, final IPushEventHandler<EventType> handler) { return installNode(component, handler, _defaultPollingInterval); }
protected void onTimer(final AjaxRequestTarget target) final TimerPushService pushService = TimerPushService.get(target.getPage().getApplication()); pushService.onDisconnect(node); for (final Iterator<TimerPushEventContext<?>> it = pushService.pollEvents(node) .iterator(); it.hasNext();)
public <EventType> TimerPushNode<EventType> installNode(final Component component, final IPushEventHandler<EventType> handler, final Duration pollingInterval) { TimerPushBehavior behavior = _findPushBehaviour(component); if (behavior == null) { behavior = new TimerPushBehavior(pollingInterval); component.add(behavior); } final TimerPushNode<EventType> node = behavior.addNode(handler, pollingInterval); _onConnect(node); return node; }
public void run() { LOG.debug("Running timer push node cleanup task..."); int count = 0; for (final PushNodeState<?> state : _nodeStates.values()) synchronized (state) { if (state.isTimedOut()) { onDisconnect(state.node); count++; } } LOG.debug("Cleaned up {} timer push nodes.", count); } };
/** * {@inheritDoc} */ public <EventType> void publish(final IPushNode<EventType> node, final EventType event) { if (node instanceof TimerPushNode) { if (isConnected(node)) { @SuppressWarnings("unchecked") final PushNodeState<EventType> state = (PushNodeState<EventType>)_nodeStates.get(node); if (state != null) synchronized (state.queuedEventsLock) { state.queuedEvents.add(new TimerPushEventContext<EventType>(event, null, this)); } } } else LOG.warn("Unsupported push node type {}", node); }
/** * {@inheritDoc} */ public void destroy(final Application application) { TimerPushService.onApplicationShutdown(application); }
void onDisconnect(final TimerPushNode<?> node) { if (_nodeStates.remove(node) != null) { LOG.debug("Timer push node {} disconnected.", node); disconnectFromAllChannels(node); for (final IPushNodeDisconnectedListener listener : disconnectListeners) try { listener.onDisconnect(node); } catch (final RuntimeException ex) { LOG.error("Failed to notify " + listener, ex); } } }
/** * {@inheritDoc} */ public void uninstallNode(final Component component, final IPushNode<?> node) { if (node instanceof TimerPushNode) { final TimerPushBehavior behavior = _findPushBehaviour(component); if (behavior == null) return; if (behavior.removeNode(node) == 0) component.remove(behavior); } else LOG.warn("Unsupported push node type {}", node); } }
@SuppressWarnings("unchecked") <EventType> List<TimerPushEventContext<EventType>> pollEvents( final TimerPushNode<EventType> node) { final PushNodeState<EventType> state = (PushNodeState<EventType>)_nodeStates.get(node); if (state == null) { LOG.debug("Reconnecting push node {}...", node); _onConnect(node); return EMPTY_LIST; } synchronized (state) { state.lastPolledAt = Time.now(); if (state.queuedEvents.size() == 0) return EMPTY_LIST; final List<TimerPushEventContext<EventType>> events = state.queuedEvents; state.queuedEvents = new ArrayList<TimerPushEventContext<EventType>>(2); return events; } }
final TimerPushService pushService = TimerPushService.get(target.getPage().getApplication()); pushService.onDisconnect(node); for (final IPushEventContext<?> ctx : (List<IPushEventContext<?>>)pushService.pollEvents(node)) try
public <EventType> TimerPushNode<EventType> installNode(final Component component, final IPushEventHandler<EventType> handler, final Duration pollingInterval) { Args.notNull(component, "component"); Args.notNull(handler, "handler"); Args.notNull(pollingInterval, "pollingInterval"); TimerPushBehavior behavior = _findPushBehaviour(component); if (behavior != null && behavior.isStopped()) { component.remove(behavior); behavior = null; } if (behavior == null) { behavior = new TimerPushBehavior(pollingInterval); component.add(behavior); } final TimerPushNode<EventType> node = behavior.addNode(handler, pollingInterval); _onConnect(node); return node; }
public void run() { LOG.debug("Running timer push node cleanup task..."); final Time now = Time.now(); int count = 0; for (final PushNodeState<?> state : _nodeStates.values()) if (now.subtract(state.lastPolledAt).greaterThan(_maxTimeLag)) { onDisconnect(state.node); count++; } LOG.debug("Cleaned up {} timer push nodes.", count); } };
/** * {@inheritDoc} */ public <EventType> void publish(final IPushChannel<EventType> channel, final EventType event) { if (channel == null) throw new IllegalArgumentException("Argument [channel] must not be null"); final Set<IPushNode<?>> pnodes = nodesByChannels.get(channel); if (pnodes == null) throw new IllegalArgumentException("Unknown channel " + channel); final TimerPushEventContext<EventType> ctx = new TimerPushEventContext<EventType>(event, channel, this); // publish the event to all registered nodes for (final IPushNode<?> pnode : pnodes) { @SuppressWarnings("unchecked") final TimerPushNode<EventType> node = (TimerPushNode<EventType>)pnode; if (isConnected(node)) { @SuppressWarnings("unchecked") final PushNodeState<EventType> state = (PushNodeState<EventType>)_nodeStates.get(node); if (state != null) synchronized (state.queuedEventsLock) { state.queuedEvents.add(ctx); } } } }
/** * {@inheritDoc} */ public void destroy(final Application application) { final TimerPushService service = TimerPushService.INSTANCES.get(application); if (service != null) service.onApplicationShutdown(); }
void onDisconnect(final TimerPushNode<?> node) { if (_nodeStates.remove(node) != null) { LOG.debug("Timer push node {} disconnected.", node); disconnectFromAllChannels(node); for (final IPushNodeDisconnectedListener listener : _disconnectListeners) try { listener.onDisconnect(node); } catch (final RuntimeException ex) { LOG.error("Failed to notify " + listener, ex); } } }
/** * {@inheritDoc} */ public void uninstallNode(final Component component, final IPushNode<?> node) { Args.notNull(component, "component"); Args.notNull(node, "node"); if (node instanceof TimerPushNode) { final TimerPushBehavior behavior = _findPushBehaviour(component); if (behavior == null) return; if (behavior.removeNode(node) == 0) behavior.stop(RequestCycle.get().find(AjaxRequestTarget.class).get()); } else LOG.warn("Unsupported push node type {}", node); } }
@SuppressWarnings("unchecked") <EventType> List<TimerPushEventContext<EventType>> pollEvents( final TimerPushNode<EventType> node) { final PushNodeState<EventType> state = (PushNodeState<EventType>)_nodeStates.get(node); if (state == null) { LOG.debug("Reconnecting push node {}...", node); _onConnect(node); return Collections.EMPTY_LIST; } state.lastPolledAt = Time.now(); if (state.queuedEvents.size() == 0) return Collections.EMPTY_LIST; synchronized (state.queuedEventsLock) { final List<TimerPushEventContext<EventType>> events = state.queuedEvents; state.queuedEvents = new ArrayList<TimerPushEventContext<EventType>>(2); return events; } }
public static TimerPushService get(final Application application) { Args.notNull(application, "application"); TimerPushService service = INSTANCES.get(application); if (service == null) { service = new TimerPushService(); final TimerPushService existingInstance = INSTANCES.putIfAbsent(application, service); if (existingInstance == null) /* * If this is the first instance of this service for the given application, then * schedule the cleanup task. */ service.setCleanupInterval(Duration.seconds(60)); else // If it is not the first instance, throw it away. service = existingInstance; } return service; }