private void scheduleWriteOperation() {
    if (putWorker.isRunning()) {
      return;
    }
    putWorker.schedule(
        new Operation<Success>() {

          @Override
          public void apply(final ValueCallback<Success> callback) {
            concurrency
                .newTimer()
                .scheduleOnce(
                    delay,
                    new Runnable() {

                      @Override
                      public void run() {
                        writeValues(callback);
                      }
                    });
          }
        },
        new ValueCallback<Success>() {

          @Override
          public void onFailure(final Throwable t) {
            concurrency
                .newTimer()
                .scheduleOnce(
                    1,
                    new Runnable() {

                      @Override
                      public void run() {
                        throw new RuntimeException(t);
                      }
                    });
          }

          @Override
          public void onSuccess(final Success value) {}
        });
  }
  @Override
  public void performOperation(
      final StoreOperation<K, V> operation, final ValueCallback<Object> callback) {
    if (operation instanceof RemoveAllOperation) {
      @SuppressWarnings("unchecked")
      final RemoveAllOperation<V> removeAllOperation = (RemoveAllOperation<V>) operation;

      final String keyStartsWith = removeAllOperation.getKeyStartsWith();

      synchronized (pendingValues) {
        for (final Entry<K, Object> e : pendingValues.entrySet()) {
          if (((String) e.getKey()).startsWith(keyStartsWith)) {
            pendingValues.put(e.getKey(), REMOVE);
          }
        }
      }
      putWorker.schedule(
          new Operation<Object>() {

            @Override
            public void apply(final ValueCallback<Object> callback) {
              decorated.performOperation(operation, callback);
            }
          },
          callback);
      return;
    }

    if (operation instanceof MultiGetOperation) {
      final MultiGetOperation<K, V> multiGetOperation = (MultiGetOperation<K, V>) operation;

      final List<V> results = new ArrayList<V>(multiGetOperation.getKeys().size());
      for (final K key : multiGetOperation.getKeys()) {
        synchronized (pendingValues) {
          if (pendingValues.containsKey(key)) {
            results.add(safeGet(pendingValues.get(key)));
          }
        }

        synchronized (valuesWriting) {
          if (valuesWriting.containsKey(key)) {
            results.add(safeGet(valuesWriting.get(key)));
          }
        }

        if (results.size() == multiGetOperation.getKeys().size()) {
          multiGetOperation.pushOnCallback(results, callback);
          return;
        }
      }
    }

    // TODO can getAll be added here?

    // Log.println(this + ": Waiting for operation: " + operation);

    putWorker.schedule(
        new Operation<Object>() {

          @Override
          public void apply(final ValueCallback<Object> callback) {
            decorated.performOperation(operation, callback);
          }
        },
        callback);
  }