@Override public void runTimer() throws Exception { if (index.traceOptimisticLockErrors) { tasks.defaultExecutor().fork(this::cleanOldRecordings); } }
@Override public synchronized void runTimer() throws Exception { tasks.defaultExecutor().start(this::collectMetrics); }
/** * Returns the default executor. * * @return the execution builder which submits tasks to the default executor. */ public ExecutionBuilder defaultExecutor() { return new ExecutionBuilder(this, DEFAULT); }
/** * Calls {@link #executeWork()} in the determined executor. * <p> * This is kind of the main loop, as {@code executeWork()} will call {@code loop()} once the computation * ({@code doWork()} is finished. Using {@link ExecutionBuilder#frequency(Object, double)} this is limited to the * call frequency as determined by {@code maxCallFrequency()}. */ protected void loop() { tasks.executor(determineExecutor()).frequency(this, maxCallFrequency()).start(this::executeWork); }
/** * Forks the given computation and returns a {@link Promise} for the computed value. * <p> * Forks the computation, which means that the current <tt>CallContext</tt> is transferred to the new thread, * and returns the result of the computation as promise. * <p> * If the executor for the given category is saturated (all threads are active and the queue is full) this * will drop the computation and the promise will be sent a <tt>RejectedExecutionException</tt>. * * @param category the category which implies which executor to use. * @param computation the computation which eventually yields the resulting value * @param <V> the type of the resulting value * @return a promise which will either be eventually supplied with the result of the computation or with an error */ public <V> Promise<V> fork(String category, final Supplier<V> computation) { final Promise<V> result = new Promise<>(); executor(category).dropOnOverload(() -> result.fail(new RejectedExecutionException())).fork(() -> { try { result.success(computation.get()); } catch (Exception t) { result.fail(t); } }); return result; }
private void executeTask(final TimedTask task) { tasks.executor(TIMER) .dropOnOverload(() -> Exceptions.handle() .to(LOG) .withSystemErrorMessage( "Dropping timer task '%s' (%s) due to system overload!", task, task.getClass()) .handle()) .start(() -> { try { Watch w = Watch.start(); task.runTimer(); if (w.elapsed(TimeUnit.SECONDS, false) > 1) { LOG.WARN("TimedTask '%s' (%s) took over a second to complete! " + "Consider executing the work in a separate executor!", task, task.getClass()); } } catch (Exception t) { Exceptions.handle(LOG, t); } }); }
/** * Performs a re-index of all indices into new ones starting with the given index prefix instead of the * currently active one. * * @param prefix the new index prefix to use */ public void reIndex(String prefix) { final String newPrefix = prefix.endsWith("-") ? prefix : prefix + "-"; access.tasks.defaultExecutor().fork(new ReIndexTask(this, newPrefix)); }
@Override public void runTimer() throws Exception { tasks.defaultExecutor().start(this::runEviction); }
/** * Returns the executor for the given category. * <p> * The configuration for this executor is taken from <tt>async.executor.[category]</tt>. If no config is found, * the default values are used. * * @param category the category of the task to be executed, which implies the executor to use. * @return the execution builder which submits tasks to the appropriate executor. */ @Nonnull public ExecutionBuilder executor(String category) { return new ExecutionBuilder(this, category); }
/** * Executes the action in its own executor */ public void execute() { CallContext.setCurrent(context); tasks.executor("index-delay").fork(cmd); } }
@Override protected String doWork() throws Exception { long now = System.currentTimeMillis(); int numScheduled = 0; synchronized (waitingTasks) { Iterator<WaitingTask> iter = waitingTasks.iterator(); while (iter.hasNext()) { WaitingTask next = iter.next(); if (next.timeout > now) { return numScheduled > 0 ? "Re-Scheduled Tasks: " + numScheduled : null; } iter.remove(); tasks.executor(next.executor).start(next); numScheduled++; } } return null; }
private static void stopLifecycleParticipants() { LOG.INFO("Stopping lifecycles..."); LOG.INFO(SEPARATOR_LINE); for (int i = lifecycleStopParticipants.size() - 1; i >= 0; i--) { Stoppable stoppable = lifecycleStopParticipants.get(i); Future future = tasks.defaultExecutor().fork(() -> stopLifecycle(stoppable)); if (!future.await(Duration.ofSeconds(10))) { LOG.WARN("Lifecycle '%s' did not stop within 10 seconds....", stoppable.getClass().getName()); } } LOG.INFO(SEPARATOR_LINE); }
@Override public void runTimer() throws Exception { tasks.defaultExecutor().start(() -> Sirius.getSetup().cleanOldLogFiles(logFileRetention.toMillis())); } }
private static void startComponents() { if (started) { stop(); } boolean startFailed = false; for (final Startable lifecycle : lifecycleStartParticipants) { Future future = tasks.defaultExecutor().fork(() -> startLifecycle(lifecycle)); if (!future.await(Duration.ofMinutes(1))) { LOG.WARN("Lifecycle '%s' did not start within one minute....", lifecycle.getClass().getName()); startFailed = true; } } if (startFailed) { outputActiveOperations(); } started = true; }
/** * Updates the entity in the database asynchronous using a dedicated thread pool. * * @param entity the entity to be written into the DB * @param <E> the type of the entity to update * @return a {@link Promise} handling the update process */ public <E extends Entity> Promise<E> updateAsync(E entity) { Promise<E> promise = new Promise<>(); tasks.executor(ASYNC_UPDATER).start(() -> { try { update(entity); promise.success(entity); } catch (Exception e) { promise.fail(e); } }); return promise; }
/** * Handles a delete of the given entity. * * @param entity the entity (which must be of type {@link #getReferencedClass()}) which is going to be deleted */ public void onDelete(final Entity entity) { if (refType.cascade() == Cascade.REJECT) { rejectDeleteIfNecessary(entity); } else if (refType.cascade() == Cascade.SET_NULL) { tasks.executor(IndexAccess.ASYNC_CATEGORY_INDEX_INTEGRITY).fork(() -> setNull(entity)); } else if (refType.cascade() == Cascade.CASCADE) { tasks.executor(IndexAccess.ASYNC_CATEGORY_INDEX_INTEGRITY).fork(() -> cascadeDelete(entity)); } }
protected void handlePubSubMessage(String channel, String message, Subscriber subscriber) { tasks.executor("redis-pubsub").start(() -> { Watch w = Watch.start(); try { subscriber.onMessage(message); } catch (Exception e) { Exceptions.handle() .to(LOG) .error(e) .withSystemErrorMessage("Failed to process a message '%s' for topic '%s': %s (%s)", message, subscriber.getTopic()) .handle(); } w.submitMicroTiming("redis", channel); messageDuration.addValue(w.elapsedMillis()); }); }
@Override public void started() { databases.clear(); requiredSchemaChanges.clear(); Set<String> realms = mixing.getDesciptors() .stream() .filter(ed -> SQLEntity.class.isAssignableFrom(ed.getType())) .map(EntityDescriptor::getRealm) .collect(Collectors.toSet()); for (String realm : realms) { Extension ext = Sirius.getSettings().getExtension(EXTENSION_MIXING_JDBC, realm); if (ext.isDefault()) { OMA.LOG.INFO("Mixing is disabled for realm '%s' no configuration is present...", realm); } else { String databaseName = ext.get(KEY_DATABASE).asString(); if (dbs.hasDatabase(databaseName)) { Database primary = dbs.get(databaseName); databases.put(realm, Tuple.create(primary, determineSecondary(ext).orElse(primary))); waitForDatabaseToBecomeReady(realm, ext.get("initSql").asString()); } else { OMA.LOG.INFO( "Mixing is disabled for realm '%s' as the database '%s' is not present in the configuration...", realm, databaseName); } } } tasks.defaultExecutor().fork(this::updateSchemaAtStartup); }
/** * Handles a save of the given entity. * * @param entity the entity (which must be of type {@link #getReferencedClass()}) which is going to be saved */ @SuppressWarnings("unchecked") public void onSave(final Entity entity) { if (references.isEmpty()) { return; } boolean referenceChanged = false; for (Reference ref : references) { try { if (entity.source == null || entity.isChanged(ref.getRemoteProperty().getName(), ref.getRemoteProperty().writeToSource(entity))) { referenceChanged = true; break; } } catch (Exception e) { Exceptions.handle(e); // Just to be sure... referenceChanged = true; } } if (referenceChanged) { tasks.executor(IndexAccess.ASYNC_CATEGORY_INDEX_INTEGRITY).fork(() -> updateReferencedFields(entity)); } }