pulsar

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package pulsar is an Apache Pulsar-backed babelqueue.Transport for the BabelQueue Go runtime, on the pure-Go github.com/apache/pulsar-client-go (no CGo, no libpulsar). Producing sends the canonical envelope as the message payload and projects the contract envelope fields onto native Pulsar message properties (string→string): bq-job = URN, bq-trace-id = trace_id, bq-message-id = meta.id, plus bq-schema-version / bq-source-lang / bq-attempts — so a Java/.NET/... peer can route on bq-job without parsing the body. Consuming receives one message at a time (Receive -> process -> Ack). Per §5.2 / §5.7 the bq-job property is the routing key (the body's job is used only when bq-job is absent or blank; a differing body URN is reported to the optional OnRoutingMismatch hook) and bq-attempts is the authoritative counter (the body's attempts is used only when the property is absent or not a plain non-negative decimal integer). Before any of that, a bq-schema-version property that is present but not the core's supported version is version-gated (§5.7 step 3): the body is not decoded and the message is routed to a reserved unsupported-version URN no handler owns, so the App quarantines it through its bounded retry / dead-letter path (also under StrategyRelease, which would otherwise loop; the optional OnSchemaVersionRejected hook names the rejected version). That route is an in-process marker only: it carries the delivery's original bq-job and bq-schema-version, and a retry or dead-letter re-publish writes those back verbatim, so the sentinel never reaches the wire and a redrive meets the same gate. The result is then raised to the broker's native RedeliveryCount (no −1, because Pulsar's redelivery count is 0-based): attempts = max(bq-attempts, RedeliveryCount), so a redelivered message reflects its true count without lowering the runtime's own counter.

tr, _ := pulsar.New(pulsar.WithURL("pulsar://localhost:6650"))
app := babelqueue.NewApp(tr, babelqueue.WithDefaultQueue("orders"))

This binding implements §5 of the BabelQueue broker-bindings contract. The envelope is unchanged (schema_version stays 1); Apache Pulsar is purely additive.

Full spec: https://babelqueue.com

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client interface {
	CreateProducer(queue string) (Producer, error)
	Subscribe(queue string) (Consumer, error)
}

Client creates per-queue producers and subscriptions. A pulsarsdk.Client is wrapped to satisfy it (see WithPulsarClient); a fake satisfies it in tests.

type Consumer

type Consumer interface {
	Receive(ctx context.Context) (pulsarsdk.Message, error)
	Ack(msg pulsarsdk.Message) error
	Nack(msg pulsarsdk.Message)
}

Consumer is the subset of pulsarsdk.Consumer the transport uses.

type OnRoutingMismatch added in v1.1.0

type OnRoutingMismatch func(propertyURN, bodyURN string, env *babelqueue.Envelope)

OnRoutingMismatch is called when a message's bq-job property and its body's job name different URNs (the property wins and the message is routed on it). propertyURN is the trimmed bq-job value, bodyURN the body's job, and env the accepted envelope as the handler will see it (body unchanged, attempts reconciled) — treat it as read-only. It is not called for an envelope the consumer rejects. It is a diagnostic hook, separate from any error handling: a panic in it is recovered and ignored, and it never changes how the message is delivered, acked or retried.

type OnSchemaVersionRejected added in v1.1.0

type OnSchemaVersionRejected func(version, queue string)

OnSchemaVersionRejected is called when the version gate (§5.7 step 3) quarantines a message whose bq-schema-version property is present but not the core's supported version. version is the raw property value and queue the queue it was received from. The gate runs before the body is decoded; the App's quarantine error names the reserved route, and this hook additionally hands an operator the rejected version and queue directly (including for a body that is not valid JSON). It is a diagnostic hook: a panic in it is recovered and ignored, and it never changes how the message is delivered, acked or retried.

type Option

type Option func(*Transport)

Option customizes New.

func WithClient

func WithClient(c Client) Option

WithClient injects a Client (a fake in tests), bypassing all Pulsar wiring.

func WithMaxWaitTime

func WithMaxWaitTime(d time.Duration) Option

WithMaxWaitTime caps how long a single Pop blocks waiting for a message.

func WithOnRoutingMismatch added in v1.1.0

func WithOnRoutingMismatch(fn OnRoutingMismatch) Option

WithOnRoutingMismatch registers an optional OnRoutingMismatch hook (default: none).

func WithOnSchemaVersionRejected added in v1.1.0

func WithOnSchemaVersionRejected(fn OnSchemaVersionRejected) Option

WithOnSchemaVersionRejected registers an optional OnSchemaVersionRejected hook (default: none).

func WithPulsarClient

func WithPulsarClient(c pulsarsdk.Client) Option

WithPulsarClient wraps a preconfigured pulsarsdk.Client (e.g. built with TLS or auth), bypassing URL parsing.

func WithSubscription

func WithSubscription(name string) Option

WithSubscription sets the subscription name (default "babelqueue").

func WithSubscriptionType

func WithSubscriptionType(st pulsarsdk.SubscriptionType) Option

WithSubscriptionType sets the subscription type (default pulsarsdk.Shared).

func WithTopicPrefix

func WithTopicPrefix(prefix string) Option

WithTopicPrefix prefixes every queue name to form the topic (e.g. "persistent://public/default/"). Empty by default — the bare queue name is the topic.

func WithURL

func WithURL(url string) Option

WithURL builds the client from a Pulsar service URL (pulsar:// or pulsar+ssl://).

type Producer

type Producer interface {
	Send(ctx context.Context, msg *pulsarsdk.ProducerMessage) (pulsarsdk.MessageID, error)
}

Producer is the subset of pulsarsdk.Producer the transport uses; the concrete producer satisfies it, and a fake satisfies it in tests.

type Transport

type Transport struct {
	// contains filtered or unexported fields
}

Transport implements babelqueue.Transport over Apache Pulsar. It is safe for concurrent use; the per-queue producer/consumer caches are guarded by a mutex.

func New

func New(opts ...Option) (*Transport, error)

New builds a transport. Provide a service URL (WithURL), a preconfigured Pulsar client (WithPulsarClient), or an injected Client (WithClient).

func (*Transport) Ack

Ack acknowledges the reserved message.

func (*Transport) Pop

func (t *Transport) Pop(ctx context.Context, queue string, timeout time.Duration) (*babelqueue.ReceivedMessage, error)

Pop receives the next message, bounded by timeout (and WithMaxWaitTime). It reconciles the routing URN (bq-job, falling back to the body; set on ReceivedMessage.RouteURN, the body is not rewritten) and attempts (bq-attempts, falling back to the body, floored at RedeliveryCount; written into the body). Returns (nil, nil) when no message arrives.

func (*Transport) Publish

func (t *Transport) Publish(ctx context.Context, queue, body string) error

Publish sends body to queue with the §5 property projection.

func (*Transport) PublishRouted added in v1.1.0

func (t *Transport) PublishRouted(ctx context.Context, queue, body, routeURN string) error

PublishRouted is [Publish] with the routing property pinned: a non-empty routeURN is written as bq-job instead of the body's job, so an App retry or release re-publish keeps the original delivery's routing URN (§5.2/§5.7). A blank routeURN derives bq-job from the body.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL