Search in sources :

Example 6 with PossibleInconsistentStateException

use of org.apache.flink.runtime.persistence.PossibleInconsistentStateException in project flink by apache.

the class KubernetesStateHandleStoreTest method testAddWithPossiblyInconsistentStateHandling.

@Test
public void testAddWithPossiblyInconsistentStateHandling() throws Exception {
    new Context() {

        {
            runTest(() -> {
                leaderCallbackGrantLeadership();
                final FlinkKubeClient anotherFlinkKubeClient = createFlinkKubeClientBuilder().setCheckAndUpdateConfigMapFunction((configMapName, function) -> FutureUtils.completedExceptionally(new PossibleInconsistentStateException())).build();
                final KubernetesStateHandleStore<TestingLongStateHandleHelper.LongStateHandle> store = new KubernetesStateHandleStore<>(anotherFlinkKubeClient, LEADER_CONFIGMAP_NAME, longStateStorage, filter, LOCK_IDENTITY);
                try {
                    store.addAndLock(key, state);
                    fail("PossibleInconsistentStateException should have been thrown.");
                } catch (PossibleInconsistentStateException ex) {
                // PossibleInconsistentStateException is expected
                }
                assertThat(TestingLongStateHandleHelper.getGlobalStorageSize(), is(1));
                assertThat(TestingLongStateHandleHelper.getGlobalDiscardCount(), is(0));
            });
        }
    };
}
Also used : Arrays(java.util.Arrays) FlinkRuntimeException(org.apache.flink.util.FlinkRuntimeException) Predicate(java.util.function.Predicate) FlinkMatchers(org.apache.flink.core.testutils.FlinkMatchers) Matchers.not(org.hamcrest.Matchers.not) Test(org.junit.Test) Collectors(java.util.stream.Collectors) StringResourceVersion(org.apache.flink.runtime.persistence.StringResourceVersion) List(java.util.List) JobID(org.apache.flink.api.common.JobID) FutureUtils(org.apache.flink.util.concurrent.FutureUtils) Matchers.containsInAnyOrder(org.hamcrest.Matchers.containsInAnyOrder) FunctionUtils(org.apache.flink.util.function.FunctionUtils) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) StateHandleStore(org.apache.flink.runtime.persistence.StateHandleStore) TestingLongStateHandleHelper(org.apache.flink.runtime.persistence.TestingLongStateHandleHelper) Matchers.is(org.hamcrest.Matchers.is) Assert.fail(org.junit.Assert.fail) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) KubernetesLeaderElector(org.apache.flink.kubernetes.kubeclient.resources.KubernetesLeaderElector) Comparator(java.util.Comparator) FlinkKubeClient(org.apache.flink.kubernetes.kubeclient.FlinkKubeClient) Before(org.junit.Before) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) FlinkKubeClient(org.apache.flink.kubernetes.kubeclient.FlinkKubeClient) Test(org.junit.Test)

Example 7 with PossibleInconsistentStateException

use of org.apache.flink.runtime.persistence.PossibleInconsistentStateException in project flink by apache.

the class KubernetesStateHandleStore method addAndLock.

/**
 * Creates a state handle, stores it in ConfigMap. We could guarantee that only the leader could
 * update the ConfigMap. Since “Get(check the leader)-and-Update(write back to the ConfigMap)”
 * is a transactional operation.
 *
 * @param key Key in ConfigMap
 * @param state State to be added
 * @throws AlreadyExistException if the name already exists
 * @throws PossibleInconsistentStateException if the write-to-Kubernetes operation failed. This
 *     indicates that it's not clear whether the new state was successfully written to
 *     Kubernetes or not. No state was discarded. Proper error handling has to be applied on the
 *     caller's side.
 * @throws Exception if persisting state or writing state handle failed
 */
@Override
public RetrievableStateHandle<T> addAndLock(String key, T state) throws PossibleInconsistentStateException, Exception {
    checkNotNull(key, "Key in ConfigMap.");
    checkNotNull(state, "State.");
    final RetrievableStateHandle<T> storeHandle = storage.store(state);
    final byte[] serializedStoreHandle = serializeOrDiscard(storeHandle);
    // initialize flag to serve the failure case
    boolean discardState = true;
    try {
        // a successful operation will result in the state not being discarded
        discardState = !kubeClient.checkAndUpdateConfigMap(configMapName, c -> {
            if (isValidOperation(c)) {
                if (!c.getData().containsKey(key)) {
                    c.getData().put(key, encodeStateHandle(serializedStoreHandle));
                    return Optional.of(c);
                } else {
                    throw new CompletionException(getKeyAlreadyExistException(key));
                }
            }
            return Optional.empty();
        }).get();
        return storeHandle;
    } catch (Exception ex) {
        final Optional<PossibleInconsistentStateException> possibleInconsistentStateException = ExceptionUtils.findThrowable(ex, PossibleInconsistentStateException.class);
        if (possibleInconsistentStateException.isPresent()) {
            // it's unclear whether the state handle metadata was written to the ConfigMap -
            // hence, we don't discard the data
            discardState = false;
            throw possibleInconsistentStateException.get();
        }
        throw ExceptionUtils.findThrowable(ex, AlreadyExistException.class).orElseThrow(() -> ex);
    } finally {
        if (discardState) {
            storeHandle.discardState();
        }
    }
}
Also used : Tuple2(org.apache.flink.api.java.tuple.Tuple2) LoggerFactory(org.slf4j.LoggerFactory) StateHandleStoreUtils.deserialize(org.apache.flink.runtime.util.StateHandleStoreUtils.deserialize) ExceptionUtils(org.apache.flink.util.ExceptionUtils) HashMap(java.util.HashMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) StringResourceVersion(org.apache.flink.runtime.persistence.StringResourceVersion) KubernetesConfigMap(org.apache.flink.kubernetes.kubeclient.resources.KubernetesConfigMap) ArrayList(java.util.ArrayList) Map(java.util.Map) StateHandleStore(org.apache.flink.runtime.persistence.StateHandleStore) Preconditions.checkNotNull(org.apache.flink.util.Preconditions.checkNotNull) Nullable(javax.annotation.Nullable) RetrievableStateHandle(org.apache.flink.runtime.state.RetrievableStateHandle) Logger(org.slf4j.Logger) Predicate(java.util.function.Predicate) Collection(java.util.Collection) IOException(java.io.IOException) CompletionException(java.util.concurrent.CompletionException) Collectors(java.util.stream.Collectors) Serializable(java.io.Serializable) Base64(java.util.Base64) List(java.util.List) StateHandleStoreUtils.serializeOrDiscard(org.apache.flink.runtime.util.StateHandleStoreUtils.serializeOrDiscard) KubernetesException(org.apache.flink.kubernetes.kubeclient.resources.KubernetesException) Optional(java.util.Optional) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) RetrievableStateStorageHelper(org.apache.flink.runtime.persistence.RetrievableStateStorageHelper) KubernetesLeaderElector(org.apache.flink.kubernetes.kubeclient.resources.KubernetesLeaderElector) Collections(java.util.Collections) FlinkKubeClient(org.apache.flink.kubernetes.kubeclient.FlinkKubeClient) Optional(java.util.Optional) CompletionException(java.util.concurrent.CompletionException) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) IOException(java.io.IOException) CompletionException(java.util.concurrent.CompletionException) KubernetesException(org.apache.flink.kubernetes.kubeclient.resources.KubernetesException) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException)

Example 8 with PossibleInconsistentStateException

use of org.apache.flink.runtime.persistence.PossibleInconsistentStateException in project flink by apache.

the class KubernetesStateHandleStore method replace.

/**
 * Replaces a state handle in ConfigMap and discards the old state handle. Wo do not lock
 * resource version and then replace in Kubernetes. Since the ConfigMap is periodically updated
 * by leader, the resource version changes very fast. We use a "check-existence and update"
 * transactional operation instead.
 *
 * @param key Key in ConfigMap
 * @param resourceVersion resource version when checking existence via {@link #exists}.
 * @param state State to be added
 * @throws NotExistException if the name does not exist
 * @throws PossibleInconsistentStateException if a failure occurred during the update operation.
 *     It's unclear whether the operation actually succeeded or not. No state was discarded. The
 *     method's caller should handle this case properly.
 * @throws Exception if persisting state or writing state handle failed
 */
@Override
public void replace(String key, StringResourceVersion resourceVersion, T state) throws Exception {
    checkNotNull(key, "Key in ConfigMap.");
    checkNotNull(state, "State.");
    final RetrievableStateHandle<T> oldStateHandle = getAndLock(key);
    final RetrievableStateHandle<T> newStateHandle = storage.store(state);
    final byte[] serializedStateHandle = serializeOrDiscard(newStateHandle);
    // initialize flags to serve the failure case
    boolean discardOldState = false;
    boolean discardNewState = true;
    try {
        boolean success = kubeClient.checkAndUpdateConfigMap(configMapName, c -> {
            if (isValidOperation(c)) {
                // Check the existence
                if (c.getData().containsKey(key)) {
                    c.getData().put(key, encodeStateHandle(serializedStateHandle));
                } else {
                    throw new CompletionException(getKeyNotExistException(key));
                }
                return Optional.of(c);
            }
            return Optional.empty();
        }).get();
        // swap subject for deletion in case of success
        discardOldState = success;
        discardNewState = !success;
    } catch (Exception ex) {
        final Optional<PossibleInconsistentStateException> possibleInconsistentStateException = ExceptionUtils.findThrowable(ex, PossibleInconsistentStateException.class);
        if (possibleInconsistentStateException.isPresent()) {
            // it's unclear whether the state handle metadata was written to the ConfigMap -
            // hence, we don't discard any data
            discardNewState = false;
            throw possibleInconsistentStateException.get();
        }
        throw ExceptionUtils.findThrowable(ex, NotExistException.class).orElseThrow(() -> ex);
    } finally {
        if (discardNewState) {
            newStateHandle.discardState();
        }
        if (discardOldState) {
            oldStateHandle.discardState();
        }
    }
}
Also used : Tuple2(org.apache.flink.api.java.tuple.Tuple2) LoggerFactory(org.slf4j.LoggerFactory) StateHandleStoreUtils.deserialize(org.apache.flink.runtime.util.StateHandleStoreUtils.deserialize) ExceptionUtils(org.apache.flink.util.ExceptionUtils) HashMap(java.util.HashMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) StringResourceVersion(org.apache.flink.runtime.persistence.StringResourceVersion) KubernetesConfigMap(org.apache.flink.kubernetes.kubeclient.resources.KubernetesConfigMap) ArrayList(java.util.ArrayList) Map(java.util.Map) StateHandleStore(org.apache.flink.runtime.persistence.StateHandleStore) Preconditions.checkNotNull(org.apache.flink.util.Preconditions.checkNotNull) Nullable(javax.annotation.Nullable) RetrievableStateHandle(org.apache.flink.runtime.state.RetrievableStateHandle) Logger(org.slf4j.Logger) Predicate(java.util.function.Predicate) Collection(java.util.Collection) IOException(java.io.IOException) CompletionException(java.util.concurrent.CompletionException) Collectors(java.util.stream.Collectors) Serializable(java.io.Serializable) Base64(java.util.Base64) List(java.util.List) StateHandleStoreUtils.serializeOrDiscard(org.apache.flink.runtime.util.StateHandleStoreUtils.serializeOrDiscard) KubernetesException(org.apache.flink.kubernetes.kubeclient.resources.KubernetesException) Optional(java.util.Optional) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) RetrievableStateStorageHelper(org.apache.flink.runtime.persistence.RetrievableStateStorageHelper) KubernetesLeaderElector(org.apache.flink.kubernetes.kubeclient.resources.KubernetesLeaderElector) Collections(java.util.Collections) FlinkKubeClient(org.apache.flink.kubernetes.kubeclient.FlinkKubeClient) Optional(java.util.Optional) CompletionException(java.util.concurrent.CompletionException) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) IOException(java.io.IOException) CompletionException(java.util.concurrent.CompletionException) KubernetesException(org.apache.flink.kubernetes.kubeclient.resources.KubernetesException) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException)

Example 9 with PossibleInconsistentStateException

use of org.apache.flink.runtime.persistence.PossibleInconsistentStateException in project flink by apache.

the class Fabric8FlinkKubeClient method attemptCheckAndUpdateConfigMap.

private CompletableFuture<Boolean> attemptCheckAndUpdateConfigMap(String configMapName, Function<KubernetesConfigMap, Optional<KubernetesConfigMap>> updateFunction) {
    return CompletableFuture.supplyAsync(() -> {
        final KubernetesConfigMap configMap = getConfigMap(configMapName).orElseThrow(() -> new CompletionException(new KubernetesException("Cannot retry checkAndUpdateConfigMap with configMap " + configMapName + " because it does not exist.")));
        final Optional<KubernetesConfigMap> maybeUpdate = updateFunction.apply(configMap);
        if (maybeUpdate.isPresent()) {
            try {
                internalClient.configMaps().withName(configMapName).lockResourceVersion(maybeUpdate.get().getResourceVersion()).replace(maybeUpdate.get().getInternalResource());
                return true;
            } catch (Throwable throwable) {
                LOG.debug("Failed to update ConfigMap {} with data {}. Trying again.", configMap.getName(), configMap.getData());
                // handling here
                throw new CompletionException(new PossibleInconsistentStateException(throwable));
            }
        }
        return false;
    }, kubeClientExecutorService);
}
Also used : KubernetesConfigMap(org.apache.flink.kubernetes.kubeclient.resources.KubernetesConfigMap) CompletionException(java.util.concurrent.CompletionException) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) KubernetesException(org.apache.flink.kubernetes.kubeclient.resources.KubernetesException)

Example 10 with PossibleInconsistentStateException

use of org.apache.flink.runtime.persistence.PossibleInconsistentStateException in project flink by apache.

the class ZooKeeperStateHandleStoreTest method testFailingAddWithPossiblyInconsistentState.

/**
 * Tests that the created state handle is not discarded if ZooKeeper create fails with an
 * generic exception.
 */
@Test
public void testFailingAddWithPossiblyInconsistentState() throws Exception {
    final TestingLongStateHandleHelper stateHandleProvider = new TestingLongStateHandleHelper();
    CuratorFramework client = spy(ZOOKEEPER.getClient());
    when(client.inTransaction()).thenThrow(new RuntimeException("Expected test Exception."));
    ZooKeeperStateHandleStore<TestingLongStateHandleHelper.LongStateHandle> store = new ZooKeeperStateHandleStore<>(client, stateHandleProvider);
    // Config
    final String pathInZooKeeper = "/testAddDiscardStateHandleAfterFailure";
    final long state = 81282227L;
    try {
        // Test
        store.addAndLock(pathInZooKeeper, new TestingLongStateHandleHelper.LongStateHandle(state));
        fail("PossibleInconsistentStateException should have been thrown.");
    } catch (PossibleInconsistentStateException ignored) {
    // PossibleInconsistentStateException expected
    }
    // State handle created and not discarded
    assertEquals(1, TestingLongStateHandleHelper.getGlobalStorageSize());
    assertEquals(state, TestingLongStateHandleHelper.getStateHandleValueByIndex(0));
    assertEquals(0, TestingLongStateHandleHelper.getDiscardCallCountForStateHandleByIndex(0));
}
Also used : CuratorFramework(org.apache.flink.shaded.curator5.org.apache.curator.framework.CuratorFramework) TestingLongStateHandleHelper(org.apache.flink.runtime.persistence.TestingLongStateHandleHelper) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) Test(org.junit.Test)

Aggregations

PossibleInconsistentStateException (org.apache.flink.runtime.persistence.PossibleInconsistentStateException)10 List (java.util.List)6 Collectors (java.util.stream.Collectors)6 Test (org.junit.Test)5 IOException (java.io.IOException)4 ArrayList (java.util.ArrayList)4 Arrays (java.util.Arrays)4 HashMap (java.util.HashMap)4 Map (java.util.Map)4 Optional (java.util.Optional)4 Predicate (java.util.function.Predicate)4 FlinkMatchers (org.apache.flink.core.testutils.FlinkMatchers)4 KubernetesConfigMap (org.apache.flink.kubernetes.kubeclient.resources.KubernetesConfigMap)4 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)4 Matchers.is (org.hamcrest.Matchers.is)4 Assert.fail (org.junit.Assert.fail)4 CompletionException (java.util.concurrent.CompletionException)3 FlinkKubeClient (org.apache.flink.kubernetes.kubeclient.FlinkKubeClient)3 KubernetesException (org.apache.flink.kubernetes.kubeclient.resources.KubernetesException)3 KubernetesLeaderElector (org.apache.flink.kubernetes.kubeclient.resources.KubernetesLeaderElector)3