-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Emit the state to remove in the airbyte empty source #13725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 19 commits
3d496d5
0e275d0
78df38b
f003ad3
f24472c
d7a63b1
cbcdf92
6afbdbe
4331d10
09661f4
f1269bf
ee7fd54
156e3c4
23f943c
780fe54
c255acd
545e6ad
b2e3250
8785ad7
93c138c
7707a97
e3c881b
27adc8b
c3d9110
4ee75aa
47d0ac4
c213f71
7387b4a
ad3371d
11167e6
0f4be01
280b114
9cb57f6
fdbc10e
0ea7eba
0ae05a2
30e3475
03b0eeb
59eba26
2749453
859d81e
60917b9
c14a9b7
8c02f18
64d5389
7006dfa
ce3fd6e
d06e70e
c125b93
fb242b8
5847625
44c306c
9eb52f8
5cae07c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /* | ||
| * Copyright (c) 2022 Airbyte, Inc., all rights reserved. | ||
| */ | ||
|
|
||
| package io.airbyte.protocol.models; | ||
|
|
||
| import com.fasterxml.jackson.core.type.TypeReference; | ||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| import io.airbyte.commons.json.Jsons; | ||
| import io.vavr.control.Either; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class StateMessageHelper { | ||
|
|
||
| public static class AirbyteStateMessageListTypeReference extends TypeReference<List<AirbyteStateMessage>> {} | ||
|
||
|
|
||
| /** | ||
| * This a takes a json blob state and tries return either a legacy state in the format of a json | ||
| * object or a state message with the new format which is a list of airbyte state message. | ||
| * | ||
| * @param state | ||
| * @return Either a json blob (on the left) or a structure state message. | ||
| */ | ||
| public static Either<JsonNode, List<AirbyteStateMessage>> getTypedState(JsonNode state) { | ||
| if (state == null) { | ||
| return Either.right(new ArrayList<>()); | ||
| } | ||
| try { | ||
| return Either.right(Jsons.object(state, new AirbyteStateMessageListTypeReference())); | ||
| } catch (final IllegalArgumentException e) { | ||
| return Either.left(state); | ||
| } | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -4,30 +4,90 @@ | |||||
|
|
||||||
| package io.airbyte.workers.internal; | ||||||
|
|
||||||
| import com.fasterxml.jackson.databind.JsonNode; | ||||||
| import io.airbyte.commons.json.Jsons; | ||||||
| import io.airbyte.config.ResetSourceConfiguration; | ||||||
| import io.airbyte.config.StreamDescriptor; | ||||||
| import io.airbyte.config.WorkerSourceConfig; | ||||||
| import io.airbyte.protocol.models.AirbyteGlobalState; | ||||||
| import io.airbyte.protocol.models.AirbyteMessage; | ||||||
| import io.airbyte.protocol.models.AirbyteMessage.Type; | ||||||
| import io.airbyte.protocol.models.AirbyteStateMessage; | ||||||
| import io.airbyte.protocol.models.AirbyteStateMessage.AirbyteStateType; | ||||||
| import io.airbyte.protocol.models.AirbyteStreamState; | ||||||
| import io.airbyte.protocol.models.StateMessageHelper; | ||||||
| import io.vavr.control.Either; | ||||||
| import java.nio.file.Path; | ||||||
| import java.util.ArrayList; | ||||||
| import java.util.EmptyStackException; | ||||||
| import java.util.LinkedList; | ||||||
| import java.util.List; | ||||||
| import java.util.Optional; | ||||||
| import java.util.Queue; | ||||||
| import java.util.Stack; | ||||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||||
| import lombok.extern.slf4j.Slf4j; | ||||||
|
|
||||||
| /** | ||||||
| * This source will never emit any messages. It can be used in cases where that is helpful (hint: | ||||||
| * reset connection jobs). | ||||||
| */ | ||||||
| @Slf4j | ||||||
| public class EmptyAirbyteSource implements AirbyteSource { | ||||||
|
|
||||||
| private final AtomicBoolean hasEmittedState; | ||||||
| private final Queue<StreamDescriptor> streamDescriptors = new LinkedList<>(); | ||||||
|
||||||
| private boolean isPartialReset; | ||||||
| private boolean isStarted = false; | ||||||
| private Either<List<AirbyteStateMessage>, AirbyteStateMessage> perStreamOrGlobalState; | ||||||
|
||||||
|
|
||||||
| public EmptyAirbyteSource() { | ||||||
| hasEmittedState = new AtomicBoolean(); | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
| public void start(final WorkerSourceConfig sourceConfig, final Path jobRoot) throws Exception { | ||||||
| // no op. | ||||||
|
|
||||||
| try { | ||||||
| if (sourceConfig == null || sourceConfig.getSourceConnectionConfiguration() == null) { | ||||||
| isPartialReset = false; | ||||||
| } else { | ||||||
| ResetSourceConfiguration sourceConfiguration = Jsons.object(sourceConfig.getSourceConnectionConfiguration(), ResetSourceConfiguration.class); | ||||||
| streamDescriptors.addAll(sourceConfiguration.getStreamsToReset()); | ||||||
| if (streamDescriptors.isEmpty()) { | ||||||
|
||||||
| isPartialReset = false; | ||||||
|
||||||
| } else { | ||||||
| Either<JsonNode, List<AirbyteStateMessage>> eitherState = StateMessageHelper.getTypedState(sourceConfig.getState().getState()); | ||||||
|
||||||
| if (eitherState.isLeft()) { | ||||||
| log.error("The state is not compatible with a partial reset that have been requested"); | ||||||
| throw new IllegalStateException("Legacy state for a partial reset"); | ||||||
| } | ||||||
|
||||||
|
|
||||||
| if (eitherState.isRight()) { | ||||||
| List<AirbyteStateMessage> stateMessages = eitherState.get(); | ||||||
|
||||||
| List<AirbyteStateMessage> stateMessagesPerStreamOnly = | ||||||
|
||||||
| stateMessages.stream().filter(stateMessage -> stateMessage.getStateType() == AirbyteStateType.STREAM).toList(); | ||||||
benmoriceau marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| if (stateMessages.isEmpty()) { | ||||||
| log.error("No state has been provide, no reset will be perform, this will wun nothing"); | ||||||
|
||||||
| log.error("No state has been provide, no reset will be perform, this will wun nothing"); | |
| log.error("No state has been provide, no reset will be perform, this will run nothing"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you! this is so much easier to read!
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these conditionals are hard to follow. can you break them into smaller methods please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: typo: rename exitingState -> existingState
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| log.info("This is a partial reset, the shared state will be preserve"); | |
| log.info("This is a partial reset, the shared state will be preserved"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't be in the review because it is already in the base branch