Search in sources :

Example 1 with StringResourceVersion

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

the class KubernetesStateHandleStoreTest method testReplaceFailedWithPossiblyInconsistentState.

@Test
public void testReplaceFailedWithPossiblyInconsistentState() throws Exception {
    final PossibleInconsistentStateException updateException = new PossibleInconsistentStateException();
    new Context() {

        {
            runTest(() -> {
                leaderCallbackGrantLeadership();
                final KubernetesStateHandleStore<TestingLongStateHandleHelper.LongStateHandle> store = new KubernetesStateHandleStore<>(flinkKubeClient, LEADER_CONFIGMAP_NAME, longStateStorage, filter, LOCK_IDENTITY);
                store.addAndLock(key, state);
                final FlinkKubeClient anotherFlinkKubeClient = createFlinkKubeClientBuilder().setCheckAndUpdateConfigMapFunction((configMapName, function) -> FutureUtils.completedExceptionally(updateException)).build();
                final KubernetesStateHandleStore<TestingLongStateHandleHelper.LongStateHandle> anotherStore = new KubernetesStateHandleStore<>(anotherFlinkKubeClient, LEADER_CONFIGMAP_NAME, longStateStorage, filter, LOCK_IDENTITY);
                final StringResourceVersion resourceVersion = anotherStore.exists(key);
                assertThat(resourceVersion.isExisting(), is(true));
                try {
                    anotherStore.replace(key, resourceVersion, new TestingLongStateHandleHelper.LongStateHandle(23456L));
                    fail("An exception having a PossibleInconsistentStateException as its cause should have been thrown.");
                } catch (Exception ex) {
                    assertThat(ex, is(updateException));
                }
                assertThat(anotherStore.getAllAndLock().size(), is(1));
                // The state does not change
                assertThat(anotherStore.getAndLock(key).retrieveState(), is(state));
                assertThat(TestingLongStateHandleHelper.getGlobalStorageSize(), is(2));
                // no state was discarded
                assertThat(TestingLongStateHandleHelper.getDiscardCallCountForStateHandleByIndex(0), is(0));
                assertThat(TestingLongStateHandleHelper.getDiscardCallCountForStateHandleByIndex(1), 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) TestingLongStateHandleHelper(org.apache.flink.runtime.persistence.TestingLongStateHandleHelper) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) StringResourceVersion(org.apache.flink.runtime.persistence.StringResourceVersion) FlinkKubeClient(org.apache.flink.kubernetes.kubeclient.FlinkKubeClient) FlinkRuntimeException(org.apache.flink.util.FlinkRuntimeException) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) Test(org.junit.Test)

Example 2 with StringResourceVersion

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

the class KubernetesStateHandleStoreTest method testReplaceFailedAndDiscardState.

@Test
public void testReplaceFailedAndDiscardState() throws Exception {
    final FlinkRuntimeException updateException = new FlinkRuntimeException("Failed to update");
    new Context() {

        {
            runTest(() -> {
                leaderCallbackGrantLeadership();
                final KubernetesStateHandleStore<TestingLongStateHandleHelper.LongStateHandle> store = new KubernetesStateHandleStore<>(flinkKubeClient, LEADER_CONFIGMAP_NAME, longStateStorage, filter, LOCK_IDENTITY);
                store.addAndLock(key, state);
                final FlinkKubeClient anotherFlinkKubeClient = createFlinkKubeClientBuilder().setCheckAndUpdateConfigMapFunction((configMapName, function) -> {
                    throw updateException;
                }).build();
                final KubernetesStateHandleStore<TestingLongStateHandleHelper.LongStateHandle> anotherStore = new KubernetesStateHandleStore<>(anotherFlinkKubeClient, LEADER_CONFIGMAP_NAME, longStateStorage, filter, LOCK_IDENTITY);
                final TestingLongStateHandleHelper.LongStateHandle newState = new TestingLongStateHandleHelper.LongStateHandle(23456L);
                final StringResourceVersion resourceVersion = anotherStore.exists(key);
                assertThat(resourceVersion.isExisting(), is(true));
                try {
                    anotherStore.replace(key, resourceVersion, newState);
                    fail("We should get an exception when kube client failed to update.");
                } catch (Exception ex) {
                    assertThat(ex, FlinkMatchers.containsCause(updateException));
                }
                assertThat(anotherStore.getAllAndLock().size(), is(1));
                // The state do not change
                assertThat(anotherStore.getAndLock(key).retrieveState(), is(state));
                assertThat(TestingLongStateHandleHelper.getGlobalStorageSize(), is(2));
                assertThat(TestingLongStateHandleHelper.getDiscardCallCountForStateHandleByIndex(0), is(0));
                assertThat(TestingLongStateHandleHelper.getDiscardCallCountForStateHandleByIndex(1), is(1));
            });
        }
    };
}
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) TestingLongStateHandleHelper(org.apache.flink.runtime.persistence.TestingLongStateHandleHelper) FlinkRuntimeException(org.apache.flink.util.FlinkRuntimeException) StringResourceVersion(org.apache.flink.runtime.persistence.StringResourceVersion) FlinkKubeClient(org.apache.flink.kubernetes.kubeclient.FlinkKubeClient) FlinkRuntimeException(org.apache.flink.util.FlinkRuntimeException) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) Test(org.junit.Test)

Example 3 with StringResourceVersion

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

the class KubernetesStateHandleStoreTest method testReplace.

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

        {
            runTest(() -> {
                leaderCallbackGrantLeadership();
                final KubernetesStateHandleStore<TestingLongStateHandleHelper.LongStateHandle> store = new KubernetesStateHandleStore<>(flinkKubeClient, LEADER_CONFIGMAP_NAME, longStateStorage, filter, LOCK_IDENTITY);
                store.addAndLock(key, state);
                final TestingLongStateHandleHelper.LongStateHandle newState = new TestingLongStateHandleHelper.LongStateHandle(23456L);
                final StringResourceVersion resourceVersion = store.exists(key);
                store.replace(key, resourceVersion, newState);
                assertThat(store.getAllAndLock().size(), is(1));
                assertThat(store.getAndLock(key).retrieveState(), is(newState));
            });
        }
    };
}
Also used : TestingLongStateHandleHelper(org.apache.flink.runtime.persistence.TestingLongStateHandleHelper) StringResourceVersion(org.apache.flink.runtime.persistence.StringResourceVersion) Test(org.junit.Test)

Example 4 with StringResourceVersion

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

the class KubernetesStateHandleStoreTest method testReplaceWithNoLeadershipAndDiscardState.

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

        {
            runTest(() -> {
                leaderCallbackGrantLeadership();
                final KubernetesStateHandleStore<TestingLongStateHandleHelper.LongStateHandle> store = new KubernetesStateHandleStore<>(flinkKubeClient, LEADER_CONFIGMAP_NAME, longStateStorage, filter, LOCK_IDENTITY);
                final TestingLongStateHandleHelper.LongStateHandle newState = new TestingLongStateHandleHelper.LongStateHandle(23456L);
                store.addAndLock(key, state);
                // Lost leadership
                getLeaderCallback().notLeader();
                electionEventHandler.waitForRevokeLeader(TIMEOUT);
                getLeaderConfigMap().getAnnotations().remove(KubernetesLeaderElector.LEADER_ANNOTATION_KEY);
                final StringResourceVersion resourceVersion = store.exists(key);
                store.replace(key, resourceVersion, newState);
                assertThat(store.getAllAndLock().size(), is(1));
                // The state do not change
                assertThat(store.getAndLock(key).retrieveState(), is(state));
                assertThat(TestingLongStateHandleHelper.getGlobalStorageSize(), is(2));
                assertThat(TestingLongStateHandleHelper.getDiscardCallCountForStateHandleByIndex(0), is(0));
                assertThat(TestingLongStateHandleHelper.getDiscardCallCountForStateHandleByIndex(1), is(1));
            });
        }
    };
}
Also used : TestingLongStateHandleHelper(org.apache.flink.runtime.persistence.TestingLongStateHandleHelper) StringResourceVersion(org.apache.flink.runtime.persistence.StringResourceVersion) Test(org.junit.Test)

Example 5 with StringResourceVersion

use of org.apache.flink.runtime.persistence.StringResourceVersion 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)

Aggregations

StringResourceVersion (org.apache.flink.runtime.persistence.StringResourceVersion)5 TestingLongStateHandleHelper (org.apache.flink.runtime.persistence.TestingLongStateHandleHelper)4 Test (org.junit.Test)4 List (java.util.List)3 Predicate (java.util.function.Predicate)3 Collectors (java.util.stream.Collectors)3 FlinkKubeClient (org.apache.flink.kubernetes.kubeclient.FlinkKubeClient)3 KubernetesLeaderElector (org.apache.flink.kubernetes.kubeclient.resources.KubernetesLeaderElector)3 PossibleInconsistentStateException (org.apache.flink.runtime.persistence.PossibleInconsistentStateException)3 StateHandleStore (org.apache.flink.runtime.persistence.StateHandleStore)3 Arrays (java.util.Arrays)2 Comparator (java.util.Comparator)2 JobID (org.apache.flink.api.common.JobID)2 FlinkMatchers (org.apache.flink.core.testutils.FlinkMatchers)2 FlinkRuntimeException (org.apache.flink.util.FlinkRuntimeException)2 FutureUtils (org.apache.flink.util.concurrent.FutureUtils)2 FunctionUtils (org.apache.flink.util.function.FunctionUtils)2 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)2 Matchers.containsInAnyOrder (org.hamcrest.Matchers.containsInAnyOrder)2 IOException (java.io.IOException)1