Skip to content

destination-s3: add file transfer - #46302

Merged
Benoit Moriceau (benmoriceau) merged 12 commits into
masterfrom
stephane/10-01-destination-s3_add_file_transfer
Oct 30, 2024
Merged

destination-s3: add file transfer#46302
Benoit Moriceau (benmoriceau) merged 12 commits into
masterfrom
stephane/10-01-destination-s3_add_file_transfer

Conversation

@stephane-airbyte

@stephane-airbyte Stephane Geneix (stephane-airbyte) commented Oct 1, 2024

Copy link
Copy Markdown
Contributor

adding file transfer to destinaiton-s3

file transfer and record-based sync are exclusive. The platform will set the environment variables USE_FILE_TRANSFER to true and AIRBYTE_STAGING_DIRECTORY to the mounting point of the staging directory when the destination supports file transfer and the source enabled it in its config.
destination-s3 will check the USE_FILE_TRANSFER to decide whether to enable file transfer or record-based sync.
Record-based integration tests are all passing, and there's an extra test that makes sure file-based transfer is disabled.

@vercel

vercel Bot commented Oct 1, 2024

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
airbyte-docs ⬜️ Ignored (Inspect) Visit Preview Oct 30, 2024 7:05pm

Stephane Geneix (stephane-airbyte) commented Oct 1, 2024

Copy link
Copy Markdown
Contributor Author

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nice. This sidesteps any questions w/r/t conversion.

@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-01-destination-s3_add_file_transfer branch from 0a94310 to 7baeb75 Compare October 3, 2024 00:31
@stephane-airbyte
Stephane Geneix (stephane-airbyte) changed the base branch from stephane/09-30-cdk-java_add_file_transfer_mount_to_destinationacceptancetest to stephane/10-02-cdk-java_reorganize_the_destinationaccptancetest_to_split_out_the_actual_tests_from_all_the_util_methods October 3, 2024 00:31
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-02-cdk-java_reorganize_the_destinationaccptancetest_to_split_out_the_actual_tests_from_all_the_util_methods branch from 6f87147 to 52c0fe1 Compare October 3, 2024 15:59
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-01-destination-s3_add_file_transfer branch from 7baeb75 to 2dd1a87 Compare October 3, 2024 15:59
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-02-cdk-java_reorganize_the_destinationaccptancetest_to_split_out_the_actual_tests_from_all_the_util_methods branch from 52c0fe1 to 95a7d03 Compare October 7, 2024 22:05
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-01-destination-s3_add_file_transfer branch from 2dd1a87 to 75cc841 Compare October 7, 2024 22:05
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-02-cdk-java_reorganize_the_destinationaccptancetest_to_split_out_the_actual_tests_from_all_the_util_methods branch from 95a7d03 to 721ddfa Compare October 8, 2024 18:27
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-01-destination-s3_add_file_transfer branch from 75cc841 to f0f2536 Compare October 8, 2024 18:28
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-01-destination-s3_add_file_transfer branch 8 times, most recently from e2bb0c0 to e1dd9ce Compare October 9, 2024 01:29
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-02-cdk-java_reorganize_the_destinationaccptancetest_to_split_out_the_actual_tests_from_all_the_util_methods branch from 721ddfa to 8a78c22 Compare October 9, 2024 17:19
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-01-destination-s3_add_file_transfer branch 2 times, most recently from a371928 to cd74813 Compare October 9, 2024 18:57
@stephane-airbyte
Stephane Geneix (stephane-airbyte) force-pushed the stephane/10-02-cdk-java_reorganize_the_destinationaccptancetest_to_split_out_the_actual_tests_from_all_the_util_methods branch from 8a78c22 to 48a9e9e Compare October 9, 2024 20:51

Stephane Geneix (stephane-airbyte) commented Oct 23, 2024

Copy link
Copy Markdown
Contributor Author

/publish-java-cdk

🕑 https://github.com/airbytehq/airbyte/actions/runs/11481639720
✅ Successfully published Java CDK version=0.48.0!

@coderabbitai

coderabbitai Bot commented Oct 23, 2024

Copy link
Copy Markdown

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stephane Geneix (stephane-airbyte) commented Oct 23, 2024

Copy link
Copy Markdown
Contributor Author

/publish-java-cdk --force=true

Error: Unexpected inputs provided: ["--force"]

@stephane-airbyte

Stephane Geneix (stephane-airbyte) commented Oct 23, 2024

Copy link
Copy Markdown
Contributor Author

/publish-java-cdk force=true

🕑 https://github.com/airbytehq/airbyte/actions/runs/11488030425
✅ Successfully published Java CDK version=0.48.0!

}
val flushFunction =
if (featureFlags.useFileTransfer()) {
FileTransferDestinationFlushFunction(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What determines whether the feature flag is set? The fact that the source is flagged as a file source? Explicit opt-in at the sync level?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair question.

Basically, we need the source configuration to have a specific parameter enabled (I don't know the details of the parameter) AND the destination needs to have supportsFileTransfer set to true in its metadata.yaml. If those 2 conditions are true, then the 2 variables are set accordingly, a common volume is mounted on both containers, and it's expected that all records are file-based instead of record-based.
If the source config has the parameter set to true and the destination doesn't support file transfer, the platform will throw an exception

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. The shim seems like it's in the best place, and the file flush function is straightforward. I didn't have enough time to go over the tests in detail, but high-level how we're adding the file option to the docker env is clear.

One question about the env variables just to help me plan for the new CDK, but that's my own curiosity.

@edgao Edward Gao (edgao) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit: had one question about the protocol

java.util.List.of(
ConfiguredAirbyteStream()
.withSyncMode(SyncMode.INCREMENTAL)
.withDestinationSyncMode(DestinationSyncMode.APPEND_DEDUP)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we just ignoring this sync mode? (.... are we expected to behave differently in overwrite/append mode?)

@aaronsteers Aaron ("AJ") Steers (aaronsteers) Oct 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edward Gao (@edgao)
I spoke with Stephane about this. Plan is to add as follow-up. For now:

  1. Same file synced twice overwrites/updates the prior version written.
  2. No support for purging old files via reset.

This matches the business requirements as I understand them in this first iteration, so I think we are good for now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice. so in particular - that means we can do a blind "write <file> to <path>", i.e. we don't need to check if the file already exists 🚛

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I think there's 2 roadblocks to being "better" about sync modes :

  1. sftp doesn't allow to see deletes. It'll only see the current state
  2. destination state would really allow us to know which files we saved without slow and expensive S3 calls (we could even store a hash in there, and add that to the file transfer protocol)

@aaronsteers Aaron ("AJ") Steers (aaronsteers) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my part, this looks good to go when ready!

@stephane-airbyte

Stephane Geneix (stephane-airbyte) commented Oct 26, 2024

Copy link
Copy Markdown
Contributor Author

I'll merge this on monday morning HI time (so probably around 9AM PST) if everyone is OK with the timing (especially Johnny Schmidt (@johnny-schmidt) and Edward Gao (@edgao) as they would have to deal with potential oncall issues). Please 👍 or 👎 this post to confirm timing of merge (I've added a 👎 and a 👍 so it's easier for everyone. Doesn't mean I'm against the timing I'm suggesting, obviously)

@benmoriceau

Copy link
Copy Markdown
Contributor

Edward Gao (@edgao) Johnny Schmidt (@johnny-schmidt) I made the fix in DetectStreamToFlush I have re-requested a review.

cdkVersionRequired = '0.46.1'
cdkVersionRequired = '0.48.0'
features = ['db-destinations', 's3-destinations']
useLocalCdk = true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to change that once the cdk is publish.

@edgao Edward Gao (edgao) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Johnny Schmidt (@johnny-schmidt) in case you have thoughts - IMO (a) in general we don't care that much about the async framework, and (b) in particular I don't care enough to figure out why the existing queue size tracker stuff isn't working as expected

lgtm from my side, had a few style nitpicks

runningFlushWorkers,
AtomicBoolean(false),
flusher,
true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use named parameters for primitive arguments

Suggested change
true
isFileTransfer = true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

workerPool: ExecutorService = Executors.newFixedThreadPool(5),
private val airbyteMessageDeserializer: AirbyteMessageDeserializer =
AirbyteMessageDeserializer(),
private val isFileTransfer: Boolean = false,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename to flushOnEveryMessage (to reflect functionality rather than usage)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// otherwise pull records until we hit the memory limit.
val newSize: Long = (memoryItem.size) + bytesRead.get()
if (newSize <= optimalBytesToRead) {
if (newSize <= optimalBytesToRead || output.isEmpty()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this accomplishing? Is this because other changes caused optimalBytesToRead to be zero?

@benmoriceau Benoit Moriceau (benmoriceau) Oct 30, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not 0 (it's 1) but one and yes it is allowing to add a record to the output disregard of the size.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the problem here was if bytesRead == 0 && memoryItem.size > optimalBytesToRead, then we never add anything to the queue. So here, regardless of memoryItem.size or optimalBytesToRead, if there's no item in the queue, we add the current one.
For fileTransfer we set optimalBytesToRead to 1 so that we force a flush for each message. but with such a small value, any message is bigger than the optimal size, which causes an infinite loop.
Note that the infinite loop could also happen if memoryItem.size() was big enough and optimalBytesToRead was small enough. With our current settings, I don't believe it's possible, but it's just a couple of setting tweaks away...

@benmoriceau

Benoit Moriceau (benmoriceau) commented Oct 30, 2024

Copy link
Copy Markdown
Contributor

/publish-java-cdk

🕑 https://github.com/airbytehq/airbyte/actions/runs/11599674873
❌ Publish Java CDK version=0.48.0 failed!

@benmoriceau

Benoit Moriceau (benmoriceau) commented Oct 30, 2024

Copy link
Copy Markdown
Contributor

/publish-java-cdk

🕑 https://github.com/airbytehq/airbyte/actions/runs/11599816233
✅ Successfully published Java CDK version=0.48.1!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/connectors Connector related issues area/documentation Improvements or additions to documentation CDK Connector Development Kit connectors/destination/s3-glue connectors/destination/s3-v2 connectors/destination/s3

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants