use of won.bot.framework.eventbot.listener.impl.ActionOnFirstEventListener in project webofneeds by researchstudio-sat.
the class EventBotActionUtils method makeAndSubscribeRemoteResponseListener.
/**
* Creates a listener that waits for the remote response to the specified message. If a SuccessResponse is received,
* the successCallback is executed, if a FailureResponse is received, the failureCallback is executed.
* @param outgoingMessage
* @param successCallback
* @param failureCallback
* @param context
* @return
*/
public static EventListener makeAndSubscribeRemoteResponseListener(final WonMessage outgoingMessage, final EventListener successCallback, final EventListener failureCallback, EventListenerContext context) {
// create an event listener that processes the remote response to the wonMessage we're about to send
EventListener listener = new ActionOnFirstEventListener(context, OriginalMessageUriRemoteResponseEventFilter.forWonMessage(outgoingMessage), new BaseEventBotAction(context) {
@Override
protected void doRun(final Event event, EventListener executingListener) throws Exception {
if (event instanceof SuccessResponseEvent) {
successCallback.onEvent(event);
} else if (event instanceof FailureResponseEvent) {
failureCallback.onEvent(event);
}
}
});
context.getEventBus().subscribe(SuccessResponseEvent.class, listener);
context.getEventBus().subscribe(FailureResponseEvent.class, listener);
return listener;
}
use of won.bot.framework.eventbot.listener.impl.ActionOnFirstEventListener in project webofneeds by researchstudio-sat.
the class InitFactoryAction method doRun.
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
if (!(event instanceof InitializeEvent) || !(getEventListenerContext().getBotContextWrapper() instanceof FactoryBotContextWrapper)) {
logger.error("InitFactoryAction can only handle InitializeEvent with FactoryBotContextWrapper");
return;
}
final boolean usedForTesting = this.usedForTesting;
final boolean doNotMatch = this.doNotMatch;
EventListenerContext ctx = getEventListenerContext();
EventBus bus = ctx.getEventBus();
FactoryBotContextWrapper botContextWrapper = (FactoryBotContextWrapper) ctx.getBotContextWrapper();
// create a targeted counter that will publish an event when the target is reached
// in this case, 0 unfinished need creations means that all needs were created
final TargetCounterDecorator creationUnfinishedCounter = new TargetCounterDecorator(ctx, new CounterImpl("creationUnfinished"), 0);
BotTrigger createFactoryNeedTrigger = new BotTrigger(ctx, Duration.ofMillis(FACTORYNEEDCREATION_DURATION_INMILLIS));
createFactoryNeedTrigger.activate();
bus.subscribe(StartFactoryNeedCreationEvent.class, new ActionOnFirstEventListener(ctx, new PublishEventAction(ctx, new StartBotTriggerCommandEvent(createFactoryNeedTrigger))));
bus.subscribe(BotTriggerEvent.class, new ActionOnTriggerEventListener(ctx, createFactoryNeedTrigger, new BaseEventBotAction(ctx) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
if (isTooManyMessagesInFlight(messagesInFlightCounter)) {
return;
}
adjustTriggerInterval(createFactoryNeedTrigger, messagesInFlightCounter);
// defined via spring
NeedProducer needProducer = ctx.getNeedProducer();
Dataset dataset = needProducer.create();
if (dataset == null && needProducer.isExhausted()) {
bus.publish(new NeedProducerExhaustedEvent());
bus.unsubscribe(executingListener);
return;
}
URI needUriFromProducer = null;
Resource needResource = WonRdfUtils.NeedUtils.getNeedResource(dataset);
if (needResource.isURIResource()) {
needUriFromProducer = URI.create(needResource.getURI());
}
if (needUriFromProducer != null) {
URI needURI = botContextWrapper.getURIFromInternal(needUriFromProducer);
if (needURI != null) {
bus.publish(new FactoryNeedCreationSkippedEvent());
} else {
bus.publish(new CreateNeedCommandEvent(dataset, botContextWrapper.getFactoryListName(), usedForTesting, doNotMatch));
}
}
}
}));
bus.subscribe(CreateNeedCommandSuccessEvent.class, new ActionOnEventListener(ctx, new MultipleActions(ctx, // decrease the creationUnfinishedCounter
new DecrementCounterAction(ctx, creationUnfinishedCounter), // count a successful need creation
new IncrementCounterAction(ctx, needCreationSuccessfulCounter), new BaseEventBotAction(ctx) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
if (event instanceof CreateNeedCommandSuccessEvent) {
CreateNeedCommandSuccessEvent needCreatedEvent = (CreateNeedCommandSuccessEvent) event;
botContextWrapper.addInternalIdToUriReference(needCreatedEvent.getNeedUriBeforeCreation(), needCreatedEvent.getNeedURI());
}
}
})));
bus.subscribe(CreateNeedCommandEvent.class, new ActionOnEventListener(ctx, new MultipleActions(ctx, // execute the need creation for the need in the event
new ExecuteCreateNeedCommandAction(ctx), // increase the needCreationStartedCounter to signal another pending creation
new IncrementCounterAction(ctx, needCreationStartedCounter), // increase the creationUnfinishedCounter to signal another pending creation
new IncrementCounterAction(ctx, creationUnfinishedCounter))));
// if a need is already created we skip the recreation of it and increase the needCreationSkippedCounter
bus.subscribe(FactoryNeedCreationSkippedEvent.class, new ActionOnEventListener(ctx, new IncrementCounterAction(ctx, needCreationSkippedCounter)));
// if a creation failed, we don't want to keep us from keeping the correct count
bus.subscribe(CreateNeedCommandFailureEvent.class, new ActionOnEventListener(ctx, new MultipleActions(ctx, // decrease the creationUnfinishedCounter
new DecrementCounterAction(ctx, creationUnfinishedCounter), // count an unsuccessful need creation
new IncrementCounterAction(ctx, needCreationFailedCounter))));
// when the needproducer is exhausted, we stop the creator (trigger) and we have to wait until all unfinished need creations finish
// when they do, the InitFactoryFinishedEvent is published
bus.subscribe(NeedProducerExhaustedEvent.class, new ActionOnFirstEventListener(ctx, new MultipleActions(ctx, new PublishEventAction(ctx, new StopBotTriggerCommandEvent(createFactoryNeedTrigger)), new BaseEventBotAction(ctx) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
// when we're called, there probably are need creations unfinished, but there may not be
// a)
// first, prepare for the case when there are unfinished need creations:
// we register a listener, waiting for the unfinished counter to reach 0
EventListener waitForUnfinishedNeedsListener = new ActionOnFirstEventListener(ctx, new TargetCounterFilter(creationUnfinishedCounter), new PublishEventAction(ctx, new InitFactoryFinishedEvent()));
bus.subscribe(TargetCountReachedEvent.class, waitForUnfinishedNeedsListener);
// now, we can check if we've already reached the target
if (creationUnfinishedCounter.getCount() <= 0) {
// ok, turned out we didn't need that listener
bus.unsubscribe(waitForUnfinishedNeedsListener);
bus.publish(new InitFactoryFinishedEvent());
}
}
})));
bus.subscribe(InitFactoryFinishedEvent.class, new ActionOnFirstEventListener(ctx, "factoryCreateStatsLogger", new BaseEventBotAction(ctx) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
logger.info("FactoryNeedCreation finished: total:{}, successful: {}, failed: {}, skipped: {}", new Object[] { needCreationStartedCounter.getCount(), needCreationSuccessfulCounter.getCount(), needCreationFailedCounter.getCount(), needCreationSkippedCounter.getCount() });
}
}));
// MessageInFlight counter handling *************************
bus.subscribe(MessageCommandEvent.class, new ActionOnEventListener(ctx, new IncrementCounterAction(ctx, messagesInFlightCounter)));
bus.subscribe(MessageCommandResultEvent.class, new ActionOnEventListener(ctx, new DecrementCounterAction(ctx, messagesInFlightCounter)));
// if we receive a message command failure, log it
bus.subscribe(MessageCommandFailureEvent.class, new ActionOnEventListener(ctx, new LogMessageCommandFailureAction(ctx)));
// Start the need creation stuff
bus.publish(new StartFactoryNeedCreationEvent());
}
use of won.bot.framework.eventbot.listener.impl.ActionOnFirstEventListener in project webofneeds by researchstudio-sat.
the class FactoryBotInitBehaviour method onActivate.
@Override
protected void onActivate(Optional<Object> message) {
subscribeWithAutoCleanup(InitializeEvent.class, new ActionOnEventListener(context, new InitFactoryAction(context)));
subscribeWithAutoCleanup(InitFactoryFinishedEvent.class, new ActionOnFirstEventListener(context, new BaseEventBotAction(context) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
FactoryBotInitBehaviour.this.deactivate();
}
}));
}
use of won.bot.framework.eventbot.listener.impl.ActionOnFirstEventListener in project webofneeds by researchstudio-sat.
the class CrawlConnectionDataBehaviour method onActivate.
@Override
protected void onActivate(Optional<Object> message) {
logger.debug("activating crawling connection data for connection {}", command.getConnectionURI());
logger.debug("will deactivate autmatically after " + abortTimeout);
LinkedDataSource linkedDataSource = context.getLinkedDataSource();
if (linkedDataSource instanceof CachingLinkedDataSource) {
URI toInvalidate = WonLinkedDataUtils.getEventContainerURIforConnectionURI(command.getConnectionURI(), linkedDataSource);
((CachingLinkedDataSource) linkedDataSource).invalidate(toInvalidate);
((CachingLinkedDataSource) linkedDataSource).invalidate(toInvalidate, command.getNeedURI());
URI remoteConnectionUri = WonLinkedDataUtils.getRemoteConnectionURIforConnectionURI(command.getConnectionURI(), linkedDataSource);
toInvalidate = WonLinkedDataUtils.getEventContainerURIforConnectionURI(remoteConnectionUri, linkedDataSource);
((CachingLinkedDataSource) linkedDataSource).invalidate(toInvalidate);
((CachingLinkedDataSource) linkedDataSource).invalidate(toInvalidate, command.getNeedURI());
}
context.getTaskScheduler().schedule(new Runnable() {
@Override
public void run() {
deactivate();
}
}, new Date(System.currentTimeMillis() + abortTimeout.toMillis()));
;
List<Path> propertyPaths = new ArrayList<>();
PrefixMapping pmap = new PrefixMappingImpl();
pmap.withDefaultMappings(PrefixMapping.Standard);
pmap.setNsPrefix("won", WON.getURI());
pmap.setNsPrefix("msg", WONMSG.getURI());
propertyPaths.add(PathParser.parse("won:hasEventContainer", pmap));
propertyPaths.add(PathParser.parse("won:hasEventContainer/rdfs:member", pmap));
CrawlCommandEvent crawlNeedCommandEvent = new CrawlCommandEvent(command.getNeedURI(), command.getNeedURI(), propertyPaths, 10000, 5);
propertyPaths = new ArrayList();
propertyPaths.add(PathParser.parse("won:hasEventContainer", pmap));
propertyPaths.add(PathParser.parse("won:hasEventContainer/rdfs:member", pmap));
propertyPaths.add(PathParser.parse("won:hasEventContainer/rdfs:member/msg:hasCorrespondingRemoteMessage", pmap));
propertyPaths.add(PathParser.parse("won:hasRemoteNeed", pmap));
propertyPaths.add(PathParser.parse("won:hasRemoteNeed/won:hasEventContainer", pmap));
propertyPaths.add(PathParser.parse("won:hasRemoteNeed/won:hasEventContainer/rdfs:member", pmap));
propertyPaths.add(PathParser.parse("won:hasRemoteConnection", pmap));
propertyPaths.add(PathParser.parse("won:hasRemoteConnection/won:hasEventContainer", pmap));
propertyPaths.add(PathParser.parse("won:hasRemoteConnection/won:hasEventContainer/rdfs:member", pmap));
propertyPaths.add(PathParser.parse("won:hasRemoteConnection/won:hasEventContainer/rdfs:member/msg:hasCorrespondingRemoteMessage", pmap));
CrawlCommandEvent crawlConnectionCommandEvent = new CrawlCommandEvent(command.getNeedURI(), command.getConnectionURI(), propertyPaths, 10000, 5);
Dataset crawledData = DatasetFactory.createGeneral();
// add crawlcommand listener
this.subscribeWithAutoCleanup(CrawlCommandEvent.class, new ActionOnEventListener(context, new OrFilter(new SameEventFilter(crawlNeedCommandEvent), new SameEventFilter(crawlConnectionCommandEvent)), new CrawlAction(context)));
// when the first crawl succeeds, start the second
this.subscribeWithAutoCleanup(CrawlCommandSuccessEvent.class, new ActionOnEventListener(context, new CommandResultFilter(crawlNeedCommandEvent), new BaseEventBotAction(context) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
logger.debug("finished crawling need data. ");
Dataset dataset = ((CrawlCommandSuccessEvent) event).getCrawledData();
RdfUtils.addDatasetToDataset(crawledData, dataset);
// now crawl connection data
context.getEventBus().publish(crawlConnectionCommandEvent);
}
}));
// when we're done crawling, validate:
this.subscribeWithAutoCleanup(CrawlCommandSuccessEvent.class, new ActionOnEventListener(context, new CommandResultFilter(crawlConnectionCommandEvent), new BaseEventBotAction(context) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
logger.debug("finished crawling need data for connection {}", command.getConnectionURI());
Dataset dataset = ((CrawlCommandSuccessEvent) event).getCrawledData();
RdfUtils.addDatasetToDataset(crawledData, dataset);
context.getEventBus().publish(new CrawlConnectionCommandSuccessEvent(command, crawledData));
deactivate();
}
}));
// when something goes wrong, abort
this.subscribeWithAutoCleanup(CrawlCommandFailureEvent.class, new ActionOnFirstEventListener(context, new OrFilter(new CommandResultFilter(crawlConnectionCommandEvent), new CommandResultFilter(crawlNeedCommandEvent)), new BaseEventBotAction(context) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
CrawlCommandFailureEvent failureEvent = (CrawlCommandFailureEvent) event;
logger.debug("crawling failed for connection {}, message: {}", command.getConnectionURI(), failureEvent.getMessage());
context.getEventBus().publish(new CrawlConnectionCommandFailureEvent(failureEvent.getMessage(), command));
deactivate();
}
}));
// start crawling the need - connection will be crawled when need crawling is done
context.getEventBus().publish(crawlNeedCommandEvent);
}
use of won.bot.framework.eventbot.listener.impl.ActionOnFirstEventListener in project webofneeds by researchstudio-sat.
the class GroupCycleBot method initializeEventListeners.
@Override
protected void initializeEventListeners() {
EventListenerContext ctx = getEventListenerContext();
// start with a friendly message
ctx.getEventBus().subscribe(InitializeEvent.class, new ActionOnFirstEventListener(ctx, new BaseEventBotAction(ctx) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
logger.info("");
logger.info("We will create {} groups with {} members each.", NUMBER_OF_GROUPS, NUMBER_OF_GROUPMEMBERS);
logger.info("The groups all be connected to each other, resulting in {} group-group connections", NUMBER_OF_GROUPS * (NUMBER_OF_GROUPS - 1) / 2);
logger.info("Then, one group member will send a message to its group, which should reach all other group members exactly once");
logger.info("This will result in {} messages being received.", NUMBER_OF_GROUPS * NUMBER_OF_GROUPMEMBERS - 1);
logger.info("The groups will forward {} messages and suppress {} duplicates", NUMBER_OF_GROUPS * (NUMBER_OF_GROUPS + NUMBER_OF_GROUPMEMBERS - 2), (int) Math.pow(NUMBER_OF_GROUPS, 2) - 3 * NUMBER_OF_GROUPS + 2);
logger.info("");
}
}));
// understand message commands
BotBehaviour messageCommandBehaviour = new ExecuteWonMessageCommandBehaviour(ctx);
messageCommandBehaviour.activate();
// if we receive a connection message, log it
BotBehaviour logConnectionMessageBehaviour = new LogConnectionMessageBehaviour(ctx);
logConnectionMessageBehaviour.activate();
// log other important events (group/member creation and conneciton)
BotBehaviour infoBehaviour = new OutputInfoMessagesBehaviour(ctx);
infoBehaviour.activate();
// wait for both groups to finish being set up, then connect the groups
BehaviourBarrier barrier = new BehaviourBarrier(ctx);
for (int i = 0; i < NUMBER_OF_GROUPS; i++) {
// create group 1, its members, and connect them
CreateGroupBehaviour groupCreate = new CreateGroupBehaviour(ctx);
OpenOnConnectBehaviour groupOpenOnConnect = new OpenOnConnectBehaviour(ctx);
CreateGroupMembersBehaviour groupMembers = new CreateGroupMembersBehaviour(ctx);
groupCreate.onDeactivateActivate(groupOpenOnConnect, groupMembers);
barrier.waitFor(groupMembers);
// wait for the initialize event and trigger group creation
ctx.getEventBus().subscribe(InitializeEvent.class, new ActionOnFirstEventListener(ctx, new BaseEventBotAction(ctx) {
@Override
protected void doRun(Event event, EventListener executingListener) throws Exception {
groupCreate.activate();
}
}));
}
BotBehaviour connectGroupsBehaviour = new ConnectGroupsBehaviour(ctx);
barrier.thenStart(connectGroupsBehaviour);
barrier.activate();
// after connecting the groups, send one message on behalf of one of the group members
// and count the messages that group members receive
// when all groups are connected, start the count behaviour
CountReceivedMessagesBehaviour countReceivedMessagesBehaviour = new CountReceivedMessagesBehaviour(ctx);
connectGroupsBehaviour.onDeactivateActivate(countReceivedMessagesBehaviour);
// wait for the count behaviour to have started, then send the group message
BotBehaviour sendInitialMessageBehaviour = new SendOneMessageBehaviour(ctx);
countReceivedMessagesBehaviour.onActivateActivate(sendInitialMessageBehaviour);
}
Aggregations