Skip to content

Conversation

batiati
Copy link
Contributor

@batiati batiati commented Sep 1, 2025

Implements an input connector for streaming TigerBeetle events via CDC.

The CDC process is stateless, so this connector requires a cache_resource to persist progress and resume from the last acknowledged event when restarted.

  • Includes documentation and integration tests.
  • Licensing information in the file header is pending.

For more information about TigerBeetle CDC, see https://docs.tigerbeetle.com/operating/cdc/

Implements an input connector for streaming [TigerBeetle](https://tigerbeetle.com/) events via CDC.

The CDC process is stateless, so this connector requires a [`cache_resource`](https://docs.redpanda.com/redpanda-connect/components/caches/about) to persist progress and resume from the last acknowledged event when restarted.

- Includes documentation and integration tests.
- Licensing information in the file header is pending.

For more information about TigerBeetle CDC, see https://docs.tigerbeetle.com/operating/cdc/
@CLAassistant
Copy link

CLAassistant commented Sep 1, 2025

CLA assistant check
All committers have signed the CLA.

return service.NewConfigSpec().
Beta().
Categories("Services").
Version("0.0.1").
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suppose this version should be defined only once we know the release, right?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, we're actually deprecating this method as we update the docs manually these days.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The same for Beta(), when should we remove it?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah you can get rid of that, but it's also harmless to leave in.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO: Decide whether it will be included in the cloud bundle.

return nil, nil, ctx.Err()
}

func newTigerbeetleInput(config *service.ParsedConfig, resources *service.Resources) (s service.BatchInput, err error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO: Decide whether to check the enterprise license.

Suggested change
func newTigerbeetleInput(config *service.ParsedConfig, resources *service.Resources) (s service.BatchInput, err error) {
func newTigerbeetleInput(config *service.ParsedConfig, resources *service.Resources) (s service.BatchInput, err error) {
if err := license.CheckRunningEnterprise(resources); err != nil {
return nil, err
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for setting this up. I believe we're happy to go ahead with a FOSS license so no need for license checks 👍

Copy link
Collaborator

@Jeffail Jeffail left a comment

Choose a reason for hiding this comment

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

Thanks @batiati, this is great! I left a few very minor comments but only the assert one needs addressing. Extra thanks for adding the integration test ❤️

@batiati
Copy link
Contributor Author

batiati commented Sep 2, 2025

Thanks for the review @Jeffail!

The LintRules are really cool! I've implemented the validations and added unit tests for checking valid and invalid configurations.

Also, I replaced assertions that would panic with errors that will cause the connector to shut down.

Please let me know if I should add the license disclaimer to the source files. I didn't want to just copy from other files, as most say Copyright 2024 ....

}

// Extracts events from TigerBeetle.
func (input *tigerbeetleInput) produce(ctx context.Context, client tb.Client, timestampLast uint64) error {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: how about using short variable name for self?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess it would usually be named just i in Go!

I ended up using the TigerStyle coding style, favoring short but meaningful names and avoiding single-letter variables and abbreviations (except for trivial counters/indexes and well-known abbreviations like ctx, config, etc).

Although TigerStyle was originally designed for another programming language (Zig), I think we can apply most of the rules as long as they don't conflict with Go's idiomatic conventions. I don't want this code to feel alien 👽 compared with the rest of the code base!

It's your call, I'd be glad to follow your coding style otherwise.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I had a look at various inputs it feels like the "idiomatic" way in connect would be t.

@david-yu
Copy link

david-yu commented Sep 5, 2025

Hi @batiati Is this PR ready for another re-review?

@batiati
Copy link
Contributor Author

batiati commented Sep 5, 2025

Hi @batiati Is this PR ready for another re-review?

Yes, it is ready for review. I've addressed all comments so far.

@batiati
Copy link
Contributor Author

batiati commented Sep 8, 2025

CI is failing due to CGO_ENABLED: 0.

The TigerBeetle client requires CGO to consume the static library lib_tbclient (the underlying implementation of the VSR client). It includes pre-built libraries in-repo for all supported platforms.

But it seems there's a policy on builds that require external dependencies and CGO, like the ZeroMQ connector:

By default Redpanda Connect does not build with components that require linking to external libraries. If you wish to build Redpanda Connect locally with this component then set the build tag x_benthos_extra:

@josephwoodward
Copy link
Contributor

@batiati A couple more of minor comments but otherwise it's looking great!

@batiati
Copy link
Contributor Author

batiati commented Sep 9, 2025

@batiati A couple more of minor comments but otherwise it's looking great!

Thanks @josephwoodward! It's ready for another round.

@mmatczuk
Copy link
Collaborator

Could we add file headers to the Go files?

@Jeffail
Copy link
Collaborator

Jeffail commented Sep 11, 2025

CI is failing due to CGO_ENABLED: 0.

The TigerBeetle client requires CGO to consume the static library lib_tbclient (the underlying implementation of the VSR client). It includes pre-built libraries in-repo for all supported platforms.

But it seems there's a policy on builds that require external dependencies and CGO, like the ZeroMQ connector:

By default Redpanda Connect does not build with components that require linking to external libraries. If you wish to build Redpanda Connect locally with this component then set the build tag x_benthos_extra:

Ideally we'd want to find a way of getting pure Go builds so that this isn't hidden away from the majority of users. Would it be possible to use something like https://github.com/ebitengine/purego here?

@mmatczuk
Copy link
Collaborator

I think we lack batch policy configuration fieldBatchPolicy = "batching"

@batiati
Copy link
Contributor Author

batiati commented Sep 11, 2025

lack batch policy configuration fieldBatchPolicy =

@mmatczuk, initially I went with the batch policy, but some of the properties didn’t make sense for how TigerBeetle streams out CDC events (such as batching by size in bytes). Instead, we use the event_count_max config to limit the maximum number of events produced per batch.

Perhaps the batch policy could still be useful for pipeline composability. Please let me know.

@batiati
Copy link
Contributor Author

batiati commented Sep 11, 2025

Ideally we'd want to find a way of getting pure Go builds so that this isn't hidden away from the majority of users. Would it be possible to use something like https://github.com/ebitengine/purego here?

Unfortunately, Go’s standard library does not expose a general-purpose FFI or dlopen-style interface! That’s how some of the other clients work.

I know CGO can be a huge burden of complexity, but for the TigerBeetle client, adding a third-party dependency would not be worth the tradeoff either.

@mmatczuk
Copy link
Collaborator

@batiati would you be open to exploring an approach similar to opendal’s Go bindings without CGO.

@batiati
Copy link
Contributor Author

batiati commented Sep 11, 2025

@batiati would you be open to exploring an approach similar to opendal’s Go bindings without CGO.

They also use purego.

https://github.com/apache/opendal/blob/a1b810910c6d288be8bd698521f843c622673c16/bindings/go/go.mod

We are looking for alternatives in the meantime, but for the short term we can't get rid of CGO.

@batiati
Copy link
Contributor Author

batiati commented Sep 15, 2025

but for the short term we can't get rid of CGO.

Hi @Jeffail and @mmatczuk! I did some research to find alternatives, and we really can't remove the CGO dependency anytime soon. However, as we ship the client with pre-built static libraries for multiple targets, we don't depend too heavily on the system's libraries (as is the case with installing libzmq3-dev when the x_benthos_extra flag is present).

Please let me know what you suggest doing to teach the CI to build the TigerBeetle connector conditionally, and which pieces of documentation warnings we should include about it.

@Jeffail
Copy link
Collaborator

Jeffail commented Sep 19, 2025

Hey @batiati, we might try and enable CGO for some of our standard distributions of RPCN, but we almost definitely need to exclude this from our fips builds.

In order to proceed I think we should guard all of these files with a CGO build constraint so that non-cgo builds aren't broken. If you could update your PR to do this then we can merge and handle the rest in a follow-up PR, where we'll probably create fips builds with a cherry-picked list of connectors.

@batiati batiati requested a review from Jeffail September 19, 2025 15:33
@Jeffail Jeffail merged commit ddd9d52 into redpanda-data:main Sep 22, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants