001/* 002 * JGrapes Event Driven Framework 003 * Copyright (C) 2016-2018 Michael N. Lipp 004 * 005 * This program is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Affero General Public License as published by 007 * the Free Software Foundation; either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, but 011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 013 * for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License along 016 * with this program; if not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jgrapes.core; 020 021import java.util.concurrent.Callable; 022import java.util.concurrent.ExecutorService; 023import java.util.concurrent.Future; 024import org.jgrapes.core.Components.IdInfoProvider; 025 026/** 027 * An interface that describes a queue of events that are sent to the components 028 * of the associated tree. Any events fired by the components while handling 029 * an event from the pipeline are added at the end of the pipeline. 030 * 031 * An event pipeline is run by a single thread from an executor service. 032 * Adding several events to the same pipeline therefore ensures that they 033 * are executed in sequence. 034 */ 035public interface EventPipeline extends IdInfoProvider { 036 037 /** 038 * Add an event to be sent to components listening for such events on 039 * the given channels to the end of the queue. If no channels are 040 * specified as parameters, the event is fired on the event's 041 * channel (see {@link Event#channels()}). If the event doesn't 042 * specify channels either, the channel depends on how the 043 * event pipeline was obtained. Event pipelines obtained from a 044 * component's manager use the component's channel as fall back. 045 * 046 * @param <T> the event's type 047 * @param event the event to process 048 * @param channels the channels that the event was fired on 049 * @return the event (for easy chaining) 050 */ 051 <T extends Event<?>> T fire(T event, Channel... channels); 052 053 /** 054 * Allow only the given source pipeline to fire events on this 055 * pipeline. 056 * 057 * This feature can be used to ensure the proper usage of event 058 * pipelines. Assume that a handler invoked from event pipeline 059 * *S* produces several related output events and fires them 060 * using another event pipeline *O*. In this case, it is important 061 * that the proper sequence is not disturbed. By restricting 062 * the source pipeline of *O* to *S*, it becomes impossible 063 * for other threads than the one that runs the event pipeline 064 * *S* to fire events that are to be processed by *O*. 065 * 066 * Events from other threads than the one that runs *O* 067 * are ignored and an error is logged with the core package 068 * logger with ".fireRestriction" appended. 069 * 070 * @param sourcePipeline the source pipeline or `null` to 071 * revoke the restriction 072 * @return the event pipeline 073 */ 074 EventPipeline restrictEventSource(EventPipeline sourcePipeline); 075 076 /** 077 * Overrides any restriction set by 078 * {@link #restrictEventSource(EventPipeline)} for the next 079 * {@link #fire(Event, Channel...)} invocation from the calling thread. 080 * 081 * The typical use case is a protocol handling component 082 * (see the JGrapes I/O package) . After a connection and an 083 * associated IOSubchannel have been established, the response 084 * pipeline is usually only used by the downstream component, 085 * which may restrict the source for events on that pipeline. 086 * 087 * Sometimes, however, the protocol handling component must insert 088 * events with out-of-band (control) information in the stream 089 * of events that form the regular I/O data. This method allows 090 * the protocol component to do this, even if a restriction 091 * applies to the response pipeline. 092 * 093 * @return the event pipeline 094 */ 095 EventPipeline overrideRestriction(); 096 097 /** 098 * Adds an action to be executed to the event pipeline. 099 * Execution of the action is synchronized with the events 100 * on this pipeline. It will be executed after any events 101 * already fired and before any event fired subsequently. 102 * 103 * This is a short-cut for firing a special kind of event 104 * and defining a handler for only this kind of event. 105 * Submitting a callable instead of firing an event and defining 106 * a handler should only be done when no use case is imaginable 107 * in which such an event could be intercepted by other 108 * components or could trigger some action. 109 * 110 * @param <V> the value type 111 * @param name the name of the action; used in the event debug log 112 * @param action the action to execute 113 * @return the future 114 */ 115 <V> Future<V> submit(String name, Callable<V> action); 116 117 /** 118 * Like {@link #submit(String, Callable)} but without specifying a 119 * name for the event debug log. 120 * 121 * @param action the action to execute 122 */ 123 default <V> Future<V> submit(Callable<V> action) { 124 return submit(null, action); 125 } 126 127 /** 128 * Adds an action to be executed to the event pipeline. 129 * Execution of the action is synchronized with the events 130 * on this pipeline. It will be executed after any events 131 * already fired and before any event fired subsequently. 132 * 133 * This is a short-cut for firing a special kind of event 134 * and defining a handler for only this kind of event. 135 * Submitting a runnable instead of firing an event and defining 136 * a handler should only be done when no use case is imaginable 137 * in which such an event could be intercepted by other 138 * components or could trigger some action. 139 * 140 * @param name the name of the action; used in the event debug log 141 * @param action the action to execute 142 */ 143 void submit(String name, Runnable action); 144 145 /** 146 * Like {@link #submit(String, Callable)} but without specifiying 147 * a name for the event debug log. 148 * 149 * @param action the action to execute 150 */ 151 default void submit(Runnable action) { 152 submit(null, action); 153 } 154 155 /** 156 * All pipelines use the same id scope to make them uniquely identifiable 157 * by their number. 158 */ 159 @Override 160 default Class<?> idScope() { 161 return EventPipeline.class; 162 } 163 164 /** 165 * Returns the executor service used by this event pipeline to 166 * obtain its thread. If a component needs to create a thread for its 167 * own use, it should obtain it from the component's event pipeline's 168 * executor service in order to conform with standard resource 169 * management. 170 * 171 * @return the executor service 172 */ 173 ExecutorService executorService(); 174 175 /** 176 * Waits until this pipeline is empty. 177 * 178 * @throws InterruptedException 179 */ 180 void awaitExhaustion() throws InterruptedException; 181}