private IndexOperationMessage handleEdgeDelete(final QueueMessage message) { Preconditions.checkNotNull(message, "Queue Message cannot be null for handleEdgeDelete"); final AsyncEvent event = (AsyncEvent) message.getBody(); Preconditions.checkNotNull(message, "QueueMessage Body cannot be null for handleEdgeDelete"); Preconditions.checkArgument( event instanceof EdgeDeleteEvent, String.format( "Event Type for handleEdgeDelete must be EDGE_DELETE, got %s", event.getClass())); final EdgeDeleteEvent edgeDeleteEvent = (EdgeDeleteEvent) event; final ApplicationScope applicationScope = edgeDeleteEvent.getApplicationScope(); final Edge edge = edgeDeleteEvent.getEdge(); if (logger.isDebugEnabled()) { logger.debug("Deleting in app scope {} with edge {}", applicationScope, edge); } // default this observable's return to empty index operation message if nothing is emitted return eventBuilder .buildDeleteEdge(applicationScope, edge) .toBlocking() .lastOrDefault(new IndexOperationMessage()); }
private IndexOperationMessage handleEdgeIndex(final QueueMessage message) { Preconditions.checkNotNull(message, "Queue Message cannot be null for handleEdgeIndex"); final AsyncEvent event = (AsyncEvent) message.getBody(); Preconditions.checkNotNull(message, "QueueMessage Body cannot be null for handleEdgeIndex"); Preconditions.checkArgument( event instanceof EdgeIndexEvent, String.format( "Event Type for handleEdgeIndex must be EDGE_INDEX, got %s", event.getClass())); final EdgeIndexEvent edgeIndexEvent = (EdgeIndexEvent) event; final EntityCollectionManager ecm = entityCollectionManagerFactory.createCollectionManager( edgeIndexEvent.getApplicationScope()); // default this observable's return to empty index operation message if nothing is emitted return ecm.load(edgeIndexEvent.getEntityId()) .flatMap( loadedEntity -> eventBuilder.buildNewEdge( edgeIndexEvent.getApplicationScope(), loadedEntity, edgeIndexEvent.getEdge())) .toBlocking() .lastOrDefault(new IndexOperationMessage()); }
private IndexOperationMessage handleEntityIndexUpdate(final QueueMessage message) { Preconditions.checkNotNull(message, "Queue Message cannot be null for handleEntityIndexUpdate"); final AsyncEvent event = (AsyncEvent) message.getBody(); Preconditions.checkNotNull( message, "QueueMessage Body cannot be null for handleEntityIndexUpdate"); Preconditions.checkArgument( event instanceof EntityIndexEvent, String.format( "Event Type for handleEntityIndexUpdate must be ENTITY_INDEX, got %s", event.getClass())); final EntityIndexEvent entityIndexEvent = (EntityIndexEvent) event; // process the entity immediately // only process the same version, otherwise ignore final EntityIdScope entityIdScope = entityIndexEvent.getEntityIdScope(); final ApplicationScope applicationScope = entityIdScope.getApplicationScope(); final Id entityId = entityIdScope.getId(); final long updatedAfter = entityIndexEvent.getUpdatedAfter(); final EntityIndexOperation entityIndexOperation = new EntityIndexOperation(applicationScope, entityId, updatedAfter); // default this observable's return to empty index operation message if nothing is emitted return eventBuilder .buildEntityIndex(entityIndexOperation) .toBlocking() .lastOrDefault(new IndexOperationMessage()); }
private void handleInitializeApplicationIndex( final AsyncEvent event, final QueueMessage message) { Preconditions.checkNotNull( message, "Queue Message cannot be null for handleInitializeApplicationIndex"); Preconditions.checkArgument( event instanceof InitializeApplicationIndexEvent, String.format( "Event Type for handleInitializeApplicationIndex must be APPLICATION_INDEX, got %s", event.getClass())); final InitializeApplicationIndexEvent initializeApplicationIndexEvent = (InitializeApplicationIndexEvent) event; final IndexLocationStrategy indexLocationStrategy = initializeApplicationIndexEvent.getIndexLocationStrategy(); final EntityIndex index = entityIndexFactory.createEntityIndex(indexLocationStrategy); index.initialize(); }
private IndexOperationMessage handleEntityDelete(final QueueMessage message) { Preconditions.checkNotNull(message, "Queue Message cannot be null for handleEntityDelete"); final AsyncEvent event = (AsyncEvent) message.getBody(); Preconditions.checkNotNull(message, "QueueMessage Body cannot be null for handleEntityDelete"); Preconditions.checkArgument( event instanceof EntityDeleteEvent, String.format( "Event Type for handleEntityDelete must be ENTITY_DELETE, got %s", event.getClass())); final EntityDeleteEvent entityDeleteEvent = (EntityDeleteEvent) event; final ApplicationScope applicationScope = entityDeleteEvent.getEntityIdScope().getApplicationScope(); final Id entityId = entityDeleteEvent.getEntityIdScope().getId(); if (logger.isDebugEnabled()) logger.debug( "Deleting entity id from index in app scope {} with entityId {}", applicationScope, entityId); final EventBuilderImpl.EntityDeleteResults entityDeleteResults = eventBuilder.buildEntityDelete(applicationScope, entityId); // Delete the entities and remove from graph separately entityDeleteResults.getEntitiesDeleted().toBlocking().lastOrDefault(null); entityDeleteResults.getCompactedNode().toBlocking().lastOrDefault(null); // default this observable's return to empty index operation message if nothing is emitted return entityDeleteResults .getIndexObservable() .toBlocking() .lastOrDefault(new IndexOperationMessage()); }
/** * calls the event handlers and returns a result with information on whether it needs to be ack'd * and whether it needs to be indexed * * @param messages * @return */ private List<IndexEventResult> callEventHandlers(final List<QueueMessage> messages) { if (logger.isDebugEnabled()) { logger.debug("callEventHandlers with {} message(s)", messages.size()); } Stream<IndexEventResult> indexEventResults = messages .stream() .map( message -> { if (logger.isDebugEnabled()) { logger.debug( "Queue message with ID {} has been received {} time(s)", message.getMessageId(), message.getReceiveCount()); } AsyncEvent event = null; try { event = (AsyncEvent) message.getBody(); } catch (ClassCastException cce) { logger.error("Failed to deserialize message body", cce); return new IndexEventResult( Optional.absent(), Optional.absent(), System.currentTimeMillis()); } if (event == null) { logger.error("AsyncEvent type or event is null!"); return new IndexEventResult( Optional.absent(), Optional.absent(), System.currentTimeMillis()); } final AsyncEvent thisEvent = event; if (logger.isDebugEnabled()) { logger.debug("Processing event with type {}", event.getClass().getSimpleName()); } try { IndexOperationMessage single = new IndexOperationMessage(); // normal indexing event for an entity if (event instanceof EntityIndexEvent) { single = handleEntityIndexUpdate(message); } // normal indexing event for an edge else if (event instanceof EdgeIndexEvent) { single = handleEdgeIndex(message); } // deletes are 2-part, actual IO to delete data, then queue up a de-index else if (event instanceof EdgeDeleteEvent) { single = handleEdgeDelete(message); } // deletes are 2-part, actual IO to delete data, then queue up a de-index else if (event instanceof EntityDeleteEvent) { single = handleEntityDelete(message); } // initialization has special logic, therefore a special event type and no index // operation message else if (event instanceof InitializeApplicationIndexEvent) { handleInitializeApplicationIndex(event, message); } // this is the main event that pulls the index doc from map persistence and // hands to the index producer else if (event instanceof ElasticsearchIndexEvent) { handleIndexOperation((ElasticsearchIndexEvent) event); } else if (event instanceof DeIndexOldVersionsEvent) { single = handleDeIndexOldVersionEvent((DeIndexOldVersionsEvent) event); } else { throw new Exception( "Unknown EventType for message: " + message.getStringBody().trim()); } if (!(event instanceof ElasticsearchIndexEvent) && !(event instanceof InitializeApplicationIndexEvent) && single.isEmpty()) { logger.warn( "No index operation messages came back from event processing for msg: {} ", message.getStringBody().trim()); } // if no exception happens and the QueueMessage is returned in these results, it // will get ack'd return new IndexEventResult( Optional.of(single), Optional.of(message), thisEvent.getCreationTime()); } catch (IndexDocNotFoundException e) { // this exception is throw when we wait before trying quorum read on map // persistence. // return empty event result so the event's message doesn't get ack'd if (logger.isDebugEnabled()) { logger.debug(e.getMessage()); } return new IndexEventResult( Optional.absent(), Optional.absent(), thisEvent.getCreationTime()); } catch (Exception e) { // NPEs don't have a detail message, so add something for our log statement to // identify better final String errorMessage; if (e instanceof NullPointerException) { errorMessage = "NullPointerException"; } else { errorMessage = e.getMessage(); } // if the event fails to process, log and return empty message result so it // doesn't get ack'd logger.error( "{}. Failed to process message: {}", errorMessage, message.getStringBody().trim()); return new IndexEventResult( Optional.absent(), Optional.absent(), thisEvent.getCreationTime()); } }); return indexEventResults.collect(Collectors.toList()); }