private void updateClusterState(
      final ClusterServersConfig cfg, final RedisConnection connection) {
    Future<String> future = connection.async(RedisCommands.CLUSTER_NODES);
    future.addListener(
        new FutureListener<String>() {
          @Override
          public void operationComplete(Future<String> future) throws Exception {
            if (!future.isSuccess()) {
              log.error(
                  "Can't execute CLUSTER_NODES with " + connection.getRedisClient().getAddr(),
                  future.cause());
              scheduleClusterChangeCheck(cfg);
              return;
            }

            String nodesValue = future.getNow();
            log.debug(
                "cluster nodes state from {}:\n{}",
                connection.getRedisClient().getAddr(),
                nodesValue);

            Collection<ClusterPartition> newPartitions = parsePartitions(nodesValue);
            checkMasterNodesChange(newPartitions);
            checkSlaveNodesChange(newPartitions);
            checkSlotsChange(cfg, newPartitions);
            scheduleClusterChangeCheck(cfg);
          }
        });
  }
 @SuppressWarnings("unchecked")
 private static <T> Future<T> failedFuture() {
   Future<T> future = mockFuture();
   when(future.isSuccess()).thenReturn(false);
   when(future.cause()).thenReturn(new Exception());
   return future;
 }
  private void addRemoveSlaves(
      final MasterSlaveEntry entry,
      final ClusterPartition currentPart,
      final ClusterPartition newPart) {
    Set<URI> removedSlaves = new HashSet<URI>(currentPart.getSlaveAddresses());
    removedSlaves.removeAll(newPart.getSlaveAddresses());

    for (URI uri : removedSlaves) {
      currentPart.removeSlaveAddress(uri);

      slaveDown(entry, uri.getHost(), uri.getPort(), FreezeReason.MANAGER);
      log.info("slave {} removed for slot ranges: {}", uri, currentPart.getSlotRanges());
    }

    Set<URI> addedSlaves = new HashSet<URI>(newPart.getSlaveAddresses());
    addedSlaves.removeAll(currentPart.getSlaveAddresses());
    for (final URI uri : addedSlaves) {
      Future<Void> future = entry.addSlave(uri.getHost(), uri.getPort());
      future.addListener(
          new FutureListener<Void>() {
            @Override
            public void operationComplete(Future<Void> future) throws Exception {
              if (!future.isSuccess()) {
                log.error("Can't add slave: " + uri, future.cause());
                return;
              }

              currentPart.addSlaveAddress(uri);
              entry.slaveUp(uri.getHost(), uri.getPort(), FreezeReason.MANAGER);
              log.info("slave {} added for slot ranges: {}", uri, currentPart.getSlotRanges());
            }
          });
    }
  }
Beispiel #4
0
  @Override
  public Future<Void> setupMasterEntry(String host, int port) {
    RedisClient masterClient = connectionManager.createClient(host, port);
    masterEntry =
        new ClientConnectionsEntry(
            masterClient,
            config.getMasterConnectionMinimumIdleSize(),
            config.getMasterConnectionPoolSize(),
            config.getSlaveConnectionMinimumIdleSize(),
            config.getSlaveSubscriptionConnectionPoolSize(),
            connectionManager,
            NodeType.MASTER,
            config);
    final Promise<Void> res = connectionManager.newPromise();
    Future<Void> f = writeConnectionHolder.add(masterEntry);
    Future<Void> s = pubSubConnectionHolder.add(masterEntry);
    FutureListener<Void> listener =
        new FutureListener<Void>() {
          AtomicInteger counter = new AtomicInteger(2);

          @Override
          public void operationComplete(Future<Void> future) throws Exception {
            if (!future.isSuccess()) {
              res.setFailure(future.cause());
              return;
            }
            if (counter.decrementAndGet() == 0) {
              res.setSuccess(null);
            }
          }
        };
    f.addListener(listener);
    s.addListener(listener);
    return res;
  }
  private void checkClusterState(
      final ClusterServersConfig cfg,
      final Iterator<URI> iterator,
      final AtomicReference<Throwable> lastException) {
    if (!iterator.hasNext()) {
      log.error("Can't update cluster state", lastException.get());
      scheduleClusterChangeCheck(cfg);
      return;
    }
    URI uri = iterator.next();
    Future<RedisConnection> connectionFuture = connect(cfg, uri);
    connectionFuture.addListener(
        new FutureListener<RedisConnection>() {
          @Override
          public void operationComplete(Future<RedisConnection> future) throws Exception {
            if (!future.isSuccess()) {
              lastException.set(future.cause());
              checkClusterState(cfg, iterator, lastException);
              return;
            }

            RedisConnection connection = future.getNow();
            updateClusterState(cfg, connection);
          }
        });
  }
  private Future<T> createConnection(final ClientConnectionsEntry entry) {
    final Promise<T> promise = connectionManager.newPromise();
    Future<T> connFuture = connect(entry);
    connFuture.addListener(
        new FutureListener<T>() {
          @Override
          public void operationComplete(Future<T> future) throws Exception {
            if (!future.isSuccess()) {
              releaseConnection(entry);

              promiseFailure(entry, promise, future.cause());
              return;
            }

            T conn = future.getNow();
            if (!conn.isActive()) {
              promiseFailure(entry, promise, conn);
              return;
            }

            promiseSuccessful(entry, promise, conn);
          }
        });
    return promise;
  }
 @Override
 public final void operationComplete(Future<V> future) throws Exception {
   if (future.isSuccess()) {
     onSuccess(future.get());
   } else {
     onFailure(future.cause());
   }
 }
Beispiel #8
0
 public Future<Void> add(final ClientConnectionsEntry entry) {
   Future<Void> f = entries.add(entry);
   f.addListener(
       new FutureListener<Void>() {
         @Override
         public void operationComplete(Future<Void> future) throws Exception {
           addr2Entry.put(entry.getClient().getAddr(), entry);
           pubSubEntries.add(entry);
         }
       });
   return f;
 }
  public void testSslRenegotiationRejected(ServerBootstrap sb, Bootstrap cb) throws Throwable {
    reset();

    sb.childHandler(
        new ChannelInitializer<Channel>() {
          @Override
          @SuppressWarnings("deprecation")
          public void initChannel(Channel sch) throws Exception {
            serverChannel = sch;
            serverSslHandler = serverCtx.newHandler(sch.alloc());

            sch.pipeline().addLast("ssl", serverSslHandler);
            sch.pipeline().addLast("handler", serverHandler);
          }
        });

    cb.handler(
        new ChannelInitializer<Channel>() {
          @Override
          @SuppressWarnings("deprecation")
          public void initChannel(Channel sch) throws Exception {
            clientChannel = sch;
            clientSslHandler = clientCtx.newHandler(sch.alloc());

            sch.pipeline().addLast("ssl", clientSslHandler);
            sch.pipeline().addLast("handler", clientHandler);
          }
        });

    Channel sc = sb.bind().sync().channel();
    cb.connect().sync();

    Future<Channel> clientHandshakeFuture = clientSslHandler.handshakeFuture();
    clientHandshakeFuture.sync();

    String renegotiation = "SSL_RSA_WITH_RC4_128_SHA";
    clientSslHandler.engine().setEnabledCipherSuites(new String[] {renegotiation});
    clientSslHandler.renegotiate().await();
    serverChannel.close().awaitUninterruptibly();
    clientChannel.close().awaitUninterruptibly();
    sc.close().awaitUninterruptibly();
    try {
      if (serverException.get() != null) {
        throw serverException.get();
      }
      fail();
    } catch (DecoderException e) {
      assertTrue(e.getCause() instanceof SSLHandshakeException);
    }
    if (clientException.get() != null) {
      throw clientException.get();
    }
  }
 @SuppressWarnings("unchecked")
 private static <T> Future<T> mockFuture() {
   Future<T> future = (Future<T>) mock(Future.class);
   when(future.addListener(any()))
       .then(
           invoc -> {
             GenericFutureListener<Future<T>> listener =
                 invoc.getArgumentAt(0, GenericFutureListener.class);
             listener.operationComplete(future);
             return future;
           });
   return future;
 }
  @Test
  public void testPutAsync() throws InterruptedException, ExecutionException {
    RMap<Integer, Integer> map = redisson.getMap("simple");
    Future<Integer> future = map.putAsync(2, 3);
    Assert.assertNull(future.get());

    Assert.assertEquals((Integer) 3, map.get(2));

    Future<Integer> future1 = map.putAsync(2, 4);
    Assert.assertEquals((Integer) 3, future1.get());

    Assert.assertEquals((Integer) 4, map.get(2));
  }
 @Test
 public void testConnectAsync() throws InterruptedException {
   RedisClient c = new RedisClient("localhost", 6379);
   Future<RedisConnection> f = c.connectAsync();
   final CountDownLatch l = new CountDownLatch(1);
   f.addListener(
       (FutureListener<RedisConnection>)
           future -> {
             RedisConnection conn = future.get();
             assertThat(conn.sync(RedisCommands.PING)).isEqualTo("PONG");
             l.countDown();
           });
   l.await(10, TimeUnit.SECONDS);
 }
  private Future<RedisConnection> connect(ClusterServersConfig cfg, final URI addr) {
    RedisConnection connection = nodeConnections.get(addr);
    if (connection != null) {
      return newSucceededFuture(connection);
    }

    RedisClient client = createClient(addr.getHost(), addr.getPort(), cfg.getConnectTimeout());
    final Promise<RedisConnection> result = newPromise();
    Future<RedisConnection> future = client.connectAsync();
    future.addListener(
        new FutureListener<RedisConnection>() {
          @Override
          public void operationComplete(Future<RedisConnection> future) throws Exception {
            if (!future.isSuccess()) {
              result.setFailure(future.cause());
              return;
            }

            RedisConnection connection = future.getNow();
            Promise<RedisConnection> promise = newPromise();
            connectListener.onConnect(promise, connection, null, config);
            promise.addListener(
                new FutureListener<RedisConnection>() {
                  @Override
                  public void operationComplete(Future<RedisConnection> future) throws Exception {
                    if (!future.isSuccess()) {
                      result.setFailure(future.cause());
                      return;
                    }

                    RedisConnection connection = future.getNow();
                    if (connection.isActive()) {
                      nodeConnections.put(addr, connection);
                      result.setSuccess(connection);
                    } else {
                      connection.closeAsync();
                      result.setFailure(
                          new RedisException(
                              "Connection to "
                                  + connection.getRedisClient().getAddr()
                                  + " is not active!"));
                    }
                  }
                });
          }
        });

    return result;
  }
 @Test
 public void testScriptLoadAsync() {
   redisson.getBucket("foo").set("bar");
   Future<String> r = redisson.getScript().scriptLoadAsync("return redis.call('get', 'foo')");
   Assert.assertEquals(
       "282297a0228f48cd3fc6a55de6316f31422f5d17", r.awaitUninterruptibly().getNow());
   String r1 =
       redisson
           .getScript()
           .evalSha(
               Mode.READ_ONLY,
               "282297a0228f48cd3fc6a55de6316f31422f5d17",
               RScript.ReturnType.VALUE,
               Collections.emptyList());
   Assert.assertEquals("bar", r1);
 }
  @Test
  public void testPerMethodScope() throws Exception {
    FakeTicker ticker = new FakeTicker();
    int minimumRequestThreshold = 2;
    Duration circuitOpenWindow = Duration.ofSeconds(60);
    Duration counterSlidingWindow = Duration.ofSeconds(180);
    Duration counterUpdateInterval = Duration.ofMillis(1);
    Future<Object> successFuture = successFuture();
    Future<Object> failedFuture = failedFuture();

    Function<String, CircuitBreaker> factory =
        method ->
            new CircuitBreakerBuilder(remoteServiceName)
                .minimumRequestThreshold(minimumRequestThreshold)
                .circuitOpenWindow(circuitOpenWindow)
                .counterSlidingWindow(counterSlidingWindow)
                .counterUpdateInterval(counterUpdateInterval)
                .ticker(ticker)
                .build();

    RemoteInvoker remoteInvoker = mock(RemoteInvoker.class);
    // Always return failed future for methodA
    when(remoteInvoker.invoke(any(), any(), any(), any(), eq(methodA()), any()))
        .thenReturn(failedFuture);
    // Always return success future for methodB
    when(remoteInvoker.invoke(any(), any(), any(), any(), eq(methodB()), any()))
        .thenReturn(successFuture);

    CircuitBreakerMapping mapping =
        new KeyedCircuitBreakerMapping<>(KeySelector.METHOD, factory::apply);
    CircuitBreakerRemoteInvoker stub = new CircuitBreakerRemoteInvoker(remoteInvoker, mapping);

    // CLOSED (methodA)
    for (int i = 0; i < minimumRequestThreshold + 1; i++) {
      stub.invoke(eventLoop, uri, options, codec, methodA(), args);
      ticker.advance(Duration.ofMillis(1).toNanos());
    }

    // OPEN (methodA)
    Future<Object> future1 = stub.invoke(eventLoop, uri, options, codec, methodA(), args);
    assertThat(future1.isSuccess(), is(false));
    assertThat(future1.cause(), instanceOf(FailFastException.class));

    // CLOSED (methodB)
    Future<Object> future2 = stub.invoke(eventLoop, uri, options, codec, methodB(), args);
    assertThat(future2.isSuccess(), is(true));
  }
Beispiel #16
0
  public void runCleanTask(final String name, String timeoutSetName, long currentDate) {

    final Long lastExpired = lastExpiredTime.get(name);
    long now = System.currentTimeMillis();
    if (lastExpired == null) {
      if (lastExpiredTime.putIfAbsent(name, now) != null) {
        return;
      }
    } else if (lastExpired + expireTaskExecutionDelay >= now) {
      if (!lastExpiredTime.replace(name, lastExpired, now)) {
        return;
      }
    } else {
      return;
    }

    Future<Integer> future =
        cleanupExpiredEntires(name, timeoutSetName, null, valuesAmountToClean, false);

    future.addListener(
        new FutureListener<Integer>() {
          @Override
          public void operationComplete(Future<Integer> future) throws Exception {
            executor
                .getConnectionManager()
                .getGroup()
                .schedule(
                    new Runnable() {
                      @Override
                      public void run() {
                        lastExpiredTime.remove(name, lastExpired);
                      }
                    },
                    expireTaskExecutionDelay * 3,
                    TimeUnit.SECONDS);

            if (!future.isSuccess()) {
              log.warn(
                  "Can't execute clean task for expired values. RSetCache name: " + name,
                  future.cause());
              return;
            }
          }
        });
  }
Beispiel #17
0
    @Override
    public void run() {
      Future<Integer> future =
          cleanupExpiredEntires(name, timeoutSetName, maxIdleSetName, keysLimit, multimap);

      future.addListener(
          new FutureListener<Integer>() {
            @Override
            public void operationComplete(Future<Integer> future) throws Exception {
              if (!future.isSuccess()) {
                schedule();
                return;
              }

              Integer size = future.getNow();

              if (sizeHistory.size() == 2) {
                if (sizeHistory.peekFirst() > sizeHistory.peekLast()
                    && sizeHistory.peekLast() > size) {
                  delay = Math.min(maxDelay, (int) (delay * 1.5));
                }

                //                        if (sizeHistory.peekFirst() < sizeHistory.peekLast()
                //                                && sizeHistory.peekLast() < size) {
                //                            prevDelay = Math.max(minDelay, prevDelay/2);
                //                        }

                if (sizeHistory.peekFirst() == sizeHistory.peekLast()
                    && sizeHistory.peekLast() == size) {
                  if (size == keysLimit) {
                    delay = Math.max(minDelay, delay / 4);
                  }
                  if (size == 0) {
                    delay = Math.min(maxDelay, (int) (delay * 1.5));
                  }
                }

                sizeHistory.pollFirst();
              }

              sizeHistory.add(size);
              schedule();
            }
          });
    }
  private Publisher<Integer> addListener(final RedisPubSubListener<M> pubSubListener) {
    final Promise<Integer> promise = commandExecutor.getConnectionManager().newPromise();
    Future<PubSubConnectionEntry> future =
        commandExecutor.getConnectionManager().subscribe(codec, name, pubSubListener);
    future.addListener(
        new FutureListener<PubSubConnectionEntry>() {
          @Override
          public void operationComplete(Future<PubSubConnectionEntry> future) throws Exception {
            if (!future.isSuccess()) {
              promise.setFailure(future.cause());
              return;
            }

            promise.setSuccess(System.identityHashCode(pubSubListener));
          }
        });
    return new NettyFuturePublisher<Integer>(promise);
  }
Beispiel #19
0
  @Test(timeout = 10000)
  public void testBindDeadLock() throws Exception {
    final Bootstrap bootstrapA = new Bootstrap();
    bootstrapA.group(groupA);
    bootstrapA.channel(LocalChannel.class);
    bootstrapA.handler(dummyHandler);

    final Bootstrap bootstrapB = new Bootstrap();
    bootstrapB.group(groupB);
    bootstrapB.channel(LocalChannel.class);
    bootstrapB.handler(dummyHandler);

    List<Future<?>> bindFutures = new ArrayList<Future<?>>();

    // Try to bind from each other.
    for (int i = 0; i < 1024; i++) {
      bindFutures.add(
          groupA
              .next()
              .submit(
                  new Runnable() {
                    @Override
                    public void run() {
                      bootstrapB.bind(LocalAddress.ANY);
                    }
                  }));

      bindFutures.add(
          groupB
              .next()
              .submit(
                  new Runnable() {
                    @Override
                    public void run() {
                      bootstrapA.bind(LocalAddress.ANY);
                    }
                  }));
    }

    for (Future<?> f : bindFutures) {
      f.sync();
    }
  }
  @Override
  public <T> Future<T> invoke(
      EventLoop eventLoop,
      URI uri,
      ClientOptions options,
      ClientCodec codec,
      Method method,
      Object[] args)
      throws Exception {

    final CircuitBreaker circuitBreaker;
    try {
      circuitBreaker = mapping.get(eventLoop, uri, options, codec, method, args);
    } catch (Throwable t) {
      logger.warn("Failed to get a circuit breaker from mapping", t);
      return delegate().invoke(eventLoop, uri, options, codec, method, args);
    }

    if (circuitBreaker.canRequest()) {
      final Future<T> resultFut = delegate().invoke(eventLoop, uri, options, codec, method, args);
      resultFut.addListener(
          future -> {
            if (future.isSuccess()) {
              // reports success event
              circuitBreaker.onSuccess();
            } else {
              circuitBreaker.onFailure(future.cause());
            }
          });
      return resultFut;
    } else {
      // the circuit is tripped

      // prepares a failed resultPromise
      final Promise<T> resultPromise = eventLoop.newPromise();
      resultPromise.setFailure(new FailFastException(circuitBreaker));
      codec.prepareRequest(method, args, resultPromise);

      // returns immediately without calling succeeding remote invokers
      return resultPromise;
    }
  }
  public ClusterConnectionManager(ClusterServersConfig cfg, Config config) {
    super(config);
    connectListener = new ClusterConnectionListener(cfg.getReadMode() == ReadMode.SLAVE);

    this.config = create(cfg);
    init(this.config);

    Exception lastException = null;
    for (URI addr : cfg.getNodeAddresses()) {
      Future<RedisConnection> connectionFuture = connect(cfg, addr);
      try {
        RedisConnection connection = connectionFuture.syncUninterruptibly().getNow();
        String nodesValue = connection.sync(RedisCommands.CLUSTER_NODES);

        Collection<ClusterPartition> partitions = parsePartitions(nodesValue);
        List<Future<Collection<Future<Void>>>> futures =
            new ArrayList<Future<Collection<Future<Void>>>>();
        for (ClusterPartition partition : partitions) {
          Future<Collection<Future<Void>>> masterFuture = addMasterEntry(partition, cfg);
          futures.add(masterFuture);
        }

        for (Future<Collection<Future<Void>>> masterFuture : futures) {
          masterFuture.syncUninterruptibly();
          for (Future<Void> future : masterFuture.getNow()) {
            future.syncUninterruptibly();
          }
        }
        break;
      } catch (Exception e) {
        lastException = e;
        log.warn(e.getMessage());
      }
    }

    if (lastPartitions.isEmpty()) {
      throw new RedisConnectionException("Can't connect to servers!", lastException);
    }

    scheduleClusterChangeCheck(cfg);
  }
  @Test
  public void testEvalshaAsync() {
    RScript s = redisson.getScript();
    String res = s.scriptLoad(null, "return redis.call('get', 'foo')");
    Assert.assertEquals("282297a0228f48cd3fc6a55de6316f31422f5d17", res);

    redisson.getBucket("foo").set("bar");
    String r =
        redisson
            .getScript()
            .eval(Mode.READ_ONLY, "return redis.call('get', 'foo')", RScript.ReturnType.VALUE);
    Assert.assertEquals("bar", r);
    Future<Object> r1 =
        redisson
            .getScript()
            .evalShaAsync(
                Mode.READ_ONLY,
                "282297a0228f48cd3fc6a55de6316f31422f5d17",
                RScript.ReturnType.VALUE,
                Collections.emptyList());
    Assert.assertEquals("bar", r1.awaitUninterruptibly().getNow());
  }
 @After
 public void teardown() throws Exception {
   serverChannel.close().sync();
   Future<?> serverGroup = sb.group().shutdownGracefully(0, 0, MILLISECONDS);
   Future<?> serverChildGroup = sb.childGroup().shutdownGracefully(0, 0, MILLISECONDS);
   Future<?> clientGroup = cb.group().shutdownGracefully(0, 0, MILLISECONDS);
   serverGroup.sync();
   serverChildGroup.sync();
   clientGroup.sync();
 }
 @After
 public void teardown() throws Exception {
   cleanupCapturedRequests();
   cleanupCapturedResponses();
   serverChannel.close().sync();
   Future<?> serverGroup = sb.group().shutdownGracefully(0, 0, TimeUnit.MILLISECONDS);
   Future<?> serverChildGroup = sb.childGroup().shutdownGracefully(0, 0, TimeUnit.MILLISECONDS);
   Future<?> clientGroup = cb.group().shutdownGracefully(0, 0, TimeUnit.MILLISECONDS);
   serverGroup.sync();
   serverChildGroup.sync();
   clientGroup.sync();
   clientDelegator = null;
   serverDelegator = null;
   clientChannel = null;
   serverChannel = null;
   serverConnectedChannel = null;
 }
  @Test
  public void testExceptionFilter() throws Exception {
    FakeTicker ticker = new FakeTicker();
    int minimumRequestThreshold = 2;
    Duration circuitOpenWindow = Duration.ofSeconds(60);
    Duration counterSlidingWindow = Duration.ofSeconds(180);
    Duration counterUpdateInterval = Duration.ofMillis(1);
    Future<Object> failedFuture = failedFuture();

    // a filter that ignores all exception
    ExceptionFilter exceptionFilter = (cause) -> false;

    CircuitBreaker circuitBreaker =
        new CircuitBreakerBuilder(remoteServiceName)
            .minimumRequestThreshold(minimumRequestThreshold)
            .circuitOpenWindow(circuitOpenWindow)
            .counterSlidingWindow(counterSlidingWindow)
            .counterUpdateInterval(counterUpdateInterval)
            .exceptionFilter(exceptionFilter)
            .ticker(ticker)
            .build();

    RemoteInvoker remoteInvoker = mock(RemoteInvoker.class);
    // return failed future
    when(remoteInvoker.invoke(any(), any(), any(), any(), any(), any())).thenReturn(failedFuture);

    CircuitBreakerMapping mapping =
        (eventLoop1, uri, options1, codec1, method, args1) -> circuitBreaker;
    CircuitBreakerRemoteInvoker stub = new CircuitBreakerRemoteInvoker(remoteInvoker, mapping);

    // CLOSED
    for (int i = 0; i < minimumRequestThreshold + 1; i++) {
      Future<Object> future = stub.invoke(eventLoop, uri, options, codec, methodA(), args);
      // The future is `failedFuture` itself
      assertThat(future.isSuccess(), is(false));
      // This is not a CircuitBreakerException
      assertThat(future.cause(), is(not(instanceOf(FailFastException.class))));
      ticker.advance(Duration.ofMillis(1).toNanos());
    }

    // OPEN
    Future<Object> future1 = stub.invoke(eventLoop, uri, options, codec, methodA(), args);
    // The circuit is still CLOSED
    assertThat(future1.isSuccess(), is(false));
    assertThat(future1.cause(), is(not(instanceOf(FailFastException.class))));
  }
 @Override
 public V pollLastAndOfferFirstTo(String queueName, long timeout, TimeUnit unit)
     throws InterruptedException {
   Future<V> res = pollLastAndOfferFirstToAsync(queueName, timeout, unit);
   return res.await().getNow();
 }
 @Override
 public V poll(long timeout, TimeUnit unit) throws InterruptedException {
   Future<V> res = pollAsync(timeout, unit);
   return res.await().getNow();
 }
 protected void cancelTask() {
   if (responseTask != null) {
     responseTask.cancel(true);
   }
 }
 @Override
 public V take() throws InterruptedException {
   Future<V> res = takeAsync();
   return res.await().getNow();
 }
 @SuppressWarnings("unchecked")
 private static <T> Future<T> successFuture() {
   Future<T> future = mockFuture();
   when(future.isSuccess()).thenReturn(true);
   return future;
 }