/** * Asynchronously process the given document operations as one unit * using the processing chain of this service, * and call the specified ProcessingEndpoint when done. * * @throws RuntimeException caused by a QueueFullException if this DocprocService has a bounded input queue and the queue is full * @throws IllegalStateException if this DocprocService is not accepting new incoming processings */ public void processDocumentOperations(List<DocumentOperation> documentOperations, ProcessingEndpoint endp) { addProcessing(Processing.createProcessingFromDocumentOperations(getName(), documentOperations, new CallStack(getCallStack()), endp)); }
/** * Sets a new processing stack for this service. This will be the Prototype * for the call stacks of individual processings in this service */ public void setCallStack(CallStack stack) { DocprocExecutor ex = ((getExecutor() == null) ? new DocprocExecutor(getName(), stack) : new DocprocExecutor(getExecutor(), stack)); setExecutor(ex); }
/** * <p>Do some work in this service. This will perform some processing and return * in a "short" while, as long as individual processors also returns. Note that * if the internal queue is empty when this method is called, it will block until * some work is submitted by a call to process() by another thread.</p> * * <p>This method is thread safe - multiple threads may call doWorkBlocking at any time. * Note that processors * should be non-blocking, so multiple threads should be used primarily to * utilize multiple processors.</p> * * @return always true, since if the internal queue is empty when this method is * called, it will block until some work is submitted by a call to * process() by another thread. * @throws InterruptedException if a call to this method is interrupted while waiting for data to become available */ public boolean doWorkBlocking() throws InterruptedException { return doWork(true); }
private void addProcessing(Processing processing) { if ( ! isAcceptingNewProcessings()) throw new IllegalStateException("Docproc service " + getName() + " is not accepting new incoming processings. Cannot add " + processing + " "); if ( ! queue.offer(processing)) throw new RejectedExecutionException("Docproc service " + getName() + " is busy, please try later"); }
private static JSONObject renderDocprocChains(Container container) { JSONObject ret = new JSONObject(); for (RequestHandler h : container.getRequestHandlerRegistry().allComponents()) { if (h instanceof DocumentProcessingHandler) { ComponentRegistry<DocprocService> registry = ((DocumentProcessingHandler) h).getDocprocServiceRegistry(); for (DocprocService service : registry.allComponents()) { putJson(ret, service.getId().stringValue(), renderCalls(service.getCallStack().iterator())); } } } return ret; }
DocprocExecutor ex = getExecutor(); if (ex == null) { throw new NoCallStackException(); progress = ex.process(processing); } catch (Exception e) { processingFailed(processing, processing + " failed", e); return true; processingFailed(processing, processing + " failed at " + processing.callStack().getLastPopped(), null); return true; } else if (DocumentProcessor.Progress.PERMANENT_FAILURE.equals(progress)) { processingFailed(processing, processing + " failed PERMANENTLY at " + processing.callStack().getLastPopped() + ", disabling processing service.", null); setInService(false); return true; } else {
public DocumentProcessingHandler(ComponentRegistry<DocprocService> docprocServiceRegistry, ComponentRegistry<DocumentProcessor> documentProcessorComponentRegistry, ComponentRegistry<AbstractConcreteDocumentFactory> docFactoryRegistry, DocprocThreadPoolExecutor threadPool, DocumentTypeManager documentTypeManager, ChainsModel chainsModel, SchemaMap schemaMap, Statistics statistics, Metric metric, ContainerDocumentConfig containerDocConfig) { this.docprocServiceRegistry = docprocServiceRegistry; this.docFactoryRegistry = docFactoryRegistry; this.threadPool = threadPool; this.containerDocConfig = containerDocConfig; this.documentTypeManager = documentTypeManager; DocprocService.schemaMap = schemaMap; threadPool.prestartCoreThread(); laterExecutor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false); laterExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); if (chainsModel != null) { prepareChainRegistry(chainRegistry, chainsModel, documentProcessorComponentRegistry); for (Chain<DocumentProcessor> chain : chainRegistry.allComponents()) { log.config("Setting up call stack for chain " + chain.getId()); DocprocService service = new DocprocService(chain.getId(), convertToCallStack(chain, statistics, metric), documentTypeManager); service.setInService(true); docprocServiceRegistry.register(service.getId(), service); } } }
/** * Returns the processing chain of this service. This stack can not be modified. * To change the stack, set a new one. */ // TODO: Enforce unmodifiability public CallStack getCallStack() { DocprocExecutor ex = getExecutor(); return (ex == null) ? null : ex.getCallStack(); }
private boolean doWork(boolean blocking) throws InterruptedException { Processing processing; if (blocking) { processing = queue.take(); } else { processing = queue.poll(); } if (processing == null) { //did no work, returning nothing to queue return false; } if (!isInService()) { //did no work, returning processing (because it's not empty) queue.add(processing); //always successful, since queue is unbounded return false; } boolean remove = workOn(processing); //NOTE: Exceptions are handled in here, but not Errors if (!remove) { queue.add(processing); //always successful, since queue is unbounded } return true; //NOTE: We *could* have called returnProcessing() in a finally block here, but we don't //want that, since the only thing being thrown out here is Errors, and then the Processing //can just disappear instead }
public String getName() { return getId().stringValue(); }
/** * Asynchronously process the given document operation using the processing * chain of this service. * * @throws RuntimeException caused by a QueueFullException if this DocprocService has a bounded input queue and the queue is full * @throws IllegalStateException if this DocprocService is not accepting new incoming processings */ public void process(DocumentOperation documentOperation) { process(documentOperation, null); }
private DocprocExecutor getExecutor(ComponentSpecification chain) { DocprocService service = handler.getDocprocServiceRegistry().getComponent(chain); if (service == null) { throw new IllegalArgumentException("No such chain: " + chain); } return service.getExecutor(); }
/** * Asynchronously process the given Processing using the processing * chain of this service * * @throws RuntimeException caused by a QueueFullException if this DocprocService has a bounded input queue and the queue is full * @throws IllegalStateException if this DocprocService is not accepting new incoming processings */ public void process(Processing processing) { process(processing, null); }
/** * Asynchronously process the given document put or document update using the processing * chain of this service, and call the specified ProcessingEndpoint when done. * * @throws RuntimeException caused by a QueueFullException if this DocprocService has a bounded input queue and the queue is full * @throws IllegalStateException if this DocprocService is not accepting new incoming processings */ public void process(DocumentOperation documentOperation, ProcessingEndpoint endp) { addProcessing(new Processing(getName(), documentOperation, new CallStack(getCallStack()), endp)); }
@Override public void run() { try { try { processings.addAll(requestContext.getProcessings()); } catch (Exception e) { //deserialization failed: log.log(LogLevel.WARNING, "Deserialization of message failed.", e); requestContext.processingFailed(e); return; } DocprocExecutor executor = service.getExecutor(); DocumentProcessor.Progress progress = process(executor); if (DocumentProcessor.Progress.LATER.equals(progress) && !processings.isEmpty()) { DocumentProcessor.LaterProgress laterProgress = (DocumentProcessor.LaterProgress) progress; docprocHandler.submit(this, laterProgress.getDelay()); } } catch (Error error) { try { log.log(LogLevel.FATAL, Exceptions.toMessageString(error), error); } catch (Throwable t) { // do nothing } finally { Runtime.getRuntime().halt(1); } } }
/** * <p>Do some work in this service. This will perform some processing and return * in a "short" while, as long as individual processors also returns.</p> * * <p>This method is thread safe - multiple threads may call doWork at any time. * Note that processors * should be non-blocking, so multiple threads should be used primarily to * utilize multiple processors.</p> * * @return true if some work was performed, false if no work could be performed * at this time, because there are no outstanding processings, or because * this is out of service. Note that since processings may arrive or be put * back by another thread at any time, this return value does not mean * that no work will be available if doWork as called again immediately. */ public boolean doWork() { try { return doWork(false); } catch (InterruptedException e) { //will never happen because we are not blocking throw new RuntimeException(e); } }
/** * Asynchronously process the given Processing using the processing * chain of this service, and call the specified ProcessingEndpoint when done. * * @throws RuntimeException caused by a QueueFullException if this DocprocService has a bounded input queue and the queue is full * @throws IllegalStateException if this DocprocService is not accepting new incoming processings */ public void process(Processing processing, ProcessingEndpoint endp) { processing.setServiceName(getName()); processing.setCallStack(new CallStack(getCallStack())); processing.setEndpoint(endp); addProcessing(processing); }
@Override public ContentChannel handleRequest(Request request, ResponseHandler handler) { RequestContext requestContext; if (request instanceof MbusRequest) { requestContext = new MbusRequestContext((MbusRequest) request, handler, docprocServiceRegistry, docFactoryRegistry, containerDocConfig); } else { //Other types can be added here in the future throw new IllegalArgumentException("Request type not supported: " + request); } if (!requestContext.isProcessable()) { requestContext.skip(); return null; } DocprocService service = docprocServiceRegistry.getComponent(requestContext.getServiceName()); //No need to enqueue a task if the docproc chain is empty, just forward requestContext if (service == null) { log.log(LogLevel.ERROR, "DocprocService for session '" + requestContext.getServiceName() + "' not found, returning request '" + requestContext + "'."); requestContext.processingFailed(RequestContext.ErrorCode.ERROR_PROCESSING_FAILURE, "DocprocService " + requestContext.getServiceName() + " not found."); return null; } else if (service.getExecutor().getCallStack().size() == 0) { //call stack was empty, just forward message requestContext.skip(); return null; } DocumentProcessingTask task = new DocumentProcessingTask(requestContext, this, service); submit(task); return null; }