|  | @@ -1393,22 +1393,38 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
 | 
	
		
			
				|  |  |       *         If <code>false</code> is returned, no flush happened.
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      public boolean flush(FlushRequest request) {
 | 
	
		
			
				|  |  | +        PlainActionFuture<Boolean> future = new PlainActionFuture<>();
 | 
	
		
			
				|  |  | +        flush(request, future);
 | 
	
		
			
				|  |  | +        return future.actionGet();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Executes the given flush request against the engine.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param request the flush request
 | 
	
		
			
				|  |  | +     * @param listener to notify after full durability has been achieved.
 | 
	
		
			
				|  |  | +     *                 <code>false</code> if <code>waitIfOngoing==false</code>
 | 
	
		
			
				|  |  | +     *                 and an ongoing request is detected, else <code>true</code>.
 | 
	
		
			
				|  |  | +     *                 If <code>false</code> is returned, no flush happened.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void flush(FlushRequest request, ActionListener<Boolean> listener) {
 | 
	
		
			
				|  |  |          final boolean waitIfOngoing = request.waitIfOngoing();
 | 
	
		
			
				|  |  |          final boolean force = request.force();
 | 
	
		
			
				|  |  |          logger.trace("flush with {}", request);
 | 
	
		
			
				|  |  | -        /*
 | 
	
		
			
				|  |  | -         * We allow flushes while recovery since we allow operations to happen while recovering and we want to keep the translog under
 | 
	
		
			
				|  |  | -         * control (up to deletes, which we do not GC). Yet, we do not use flush internally to clear deletes and flush the index writer
 | 
	
		
			
				|  |  | -         * since we use Engine#writeIndexingBuffer for this now.
 | 
	
		
			
				|  |  | -         */
 | 
	
		
			
				|  |  | -        verifyNotClosed();
 | 
	
		
			
				|  |  | -        final long time = System.nanoTime();
 | 
	
		
			
				|  |  | -        // TODO: Transition this method to async to support async flush
 | 
	
		
			
				|  |  | -        PlainActionFuture<Engine.FlushResult> future = new PlainActionFuture<>();
 | 
	
		
			
				|  |  | -        getEngine().flush(force, waitIfOngoing, future);
 | 
	
		
			
				|  |  | -        Engine.FlushResult flushResult = future.actionGet();
 | 
	
		
			
				|  |  | -        flushMetric.inc(System.nanoTime() - time);
 | 
	
		
			
				|  |  | -        return flushResult.flushPerformed();
 | 
	
		
			
				|  |  | +        ActionListener.run(listener, l -> {
 | 
	
		
			
				|  |  | +            /*
 | 
	
		
			
				|  |  | +             * We allow flushes while recovery since we allow operations to happen while recovering and we want to keep the translog under
 | 
	
		
			
				|  |  | +             * control (up to deletes, which we do not GC). Yet, we do not use flush internally to clear deletes and flush the index writer
 | 
	
		
			
				|  |  | +             * since we use Engine#writeIndexingBuffer for this now.
 | 
	
		
			
				|  |  | +             */
 | 
	
		
			
				|  |  | +            verifyNotClosed();
 | 
	
		
			
				|  |  | +            final long startTime = System.nanoTime();
 | 
	
		
			
				|  |  | +            getEngine().flush(
 | 
	
		
			
				|  |  | +                force,
 | 
	
		
			
				|  |  | +                waitIfOngoing,
 | 
	
		
			
				|  |  | +                ActionListener.runBefore(l.map(Engine.FlushResult::flushPerformed), () -> flushMetric.inc(System.nanoTime() - startTime))
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
	
		
			
				|  | @@ -2291,25 +2307,26 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
 | 
	
		
			
				|  |  |              boolean wasActive = active.getAndSet(false);
 | 
	
		
			
				|  |  |              if (wasActive) {
 | 
	
		
			
				|  |  |                  logger.debug("flushing shard on inactive");
 | 
	
		
			
				|  |  | -                threadPool.executor(ThreadPool.Names.FLUSH).execute(new AbstractRunnable() {
 | 
	
		
			
				|  |  | -                    @Override
 | 
	
		
			
				|  |  | -                    public void onFailure(Exception e) {
 | 
	
		
			
				|  |  | -                        if (state != IndexShardState.CLOSED) {
 | 
	
		
			
				|  |  | -                            active.set(true);
 | 
	
		
			
				|  |  | -                            logger.warn("failed to flush shard on inactive", e);
 | 
	
		
			
				|  |  | +                threadPool.executor(ThreadPool.Names.FLUSH)
 | 
	
		
			
				|  |  | +                    .execute(() -> flush(new FlushRequest().waitIfOngoing(false).force(false), new ActionListener<>() {
 | 
	
		
			
				|  |  | +                        @Override
 | 
	
		
			
				|  |  | +                        public void onResponse(Boolean flushed) {
 | 
	
		
			
				|  |  | +                            if (flushed == false) {
 | 
	
		
			
				|  |  | +                                // In case an ongoing flush was detected, revert active flag so that a next flushOnIdle request
 | 
	
		
			
				|  |  | +                                // will retry (#87888)
 | 
	
		
			
				|  |  | +                                active.set(true);
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            periodicFlushMetric.inc();
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    @Override
 | 
	
		
			
				|  |  | -                    protected void doRun() {
 | 
	
		
			
				|  |  | -                        if (flush(new FlushRequest().waitIfOngoing(false).force(false)) == false) {
 | 
	
		
			
				|  |  | -                            // In case an ongoing flush was detected, revert active flag so that a next flushOnIdle request
 | 
	
		
			
				|  |  | -                            // will retry (#87888)
 | 
	
		
			
				|  |  | -                            active.set(true);
 | 
	
		
			
				|  |  | +                        @Override
 | 
	
		
			
				|  |  | +                        public void onFailure(Exception e) {
 | 
	
		
			
				|  |  | +                            if (state != IndexShardState.CLOSED) {
 | 
	
		
			
				|  |  | +                                active.set(true);
 | 
	
		
			
				|  |  | +                                logger.warn("failed to flush shard on inactive", e);
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  | -                        periodicFlushMetric.inc();
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | +                    }));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -3756,27 +3773,23 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
 | 
	
		
			
				|  |  |                   */
 | 
	
		
			
				|  |  |                  if (shouldPeriodicallyFlush()) {
 | 
	
		
			
				|  |  |                      logger.debug("submitting async flush request");
 | 
	
		
			
				|  |  | -                    final AbstractRunnable flush = new AbstractRunnable() {
 | 
	
		
			
				|  |  | -                        @Override
 | 
	
		
			
				|  |  | -                        public void onFailure(final Exception e) {
 | 
	
		
			
				|  |  | -                            if (state != IndexShardState.CLOSED) {
 | 
	
		
			
				|  |  | -                                logger.warn("failed to flush index", e);
 | 
	
		
			
				|  |  | +                    threadPool.executor(ThreadPool.Names.FLUSH).execute(() -> {
 | 
	
		
			
				|  |  | +                        flush(new FlushRequest(), new ActionListener<>() {
 | 
	
		
			
				|  |  | +                            @Override
 | 
	
		
			
				|  |  | +                            public void onResponse(Boolean flushed) {
 | 
	
		
			
				|  |  | +                                periodicFlushMetric.inc();
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                        @Override
 | 
	
		
			
				|  |  | -                        protected void doRun() {
 | 
	
		
			
				|  |  | -                            flush(new FlushRequest());
 | 
	
		
			
				|  |  | -                            periodicFlushMetric.inc();
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        @Override
 | 
	
		
			
				|  |  | -                        public void onAfter() {
 | 
	
		
			
				|  |  | -                            flushOrRollRunning.compareAndSet(true, false);
 | 
	
		
			
				|  |  | -                            afterWriteOperation();
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | -                    threadPool.executor(ThreadPool.Names.FLUSH).execute(flush);
 | 
	
		
			
				|  |  | +                            @Override
 | 
	
		
			
				|  |  | +                            public void onFailure(Exception e) {
 | 
	
		
			
				|  |  | +                                if (state != IndexShardState.CLOSED) {
 | 
	
		
			
				|  |  | +                                    logger.warn("failed to flush index", e);
 | 
	
		
			
				|  |  | +                                }
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                        });
 | 
	
		
			
				|  |  | +                        flushOrRollRunning.compareAndSet(true, false);
 | 
	
		
			
				|  |  | +                        afterWriteOperation();
 | 
	
		
			
				|  |  | +                    });
 | 
	
		
			
				|  |  |                  } else if (shouldRollTranslogGeneration()) {
 | 
	
		
			
				|  |  |                      logger.debug("submitting async roll translog generation request");
 | 
	
		
			
				|  |  |                      final AbstractRunnable roll = new AbstractRunnable() {
 |