PubSub
FTL has first-class support for PubSub, modelled on the concepts of topics (where events are sent), subscriptions (a cursor over the topic), and subscribers (functions events are delivered to). Subscribers are, as you would expect, sinks. Each subscription is a cursor over the topic it is associated with. Each topic may have multiple subscriptions. Each subscription may have multiple subscribers, in which case events will be distributed among them.
Each published event has an at least once delivery guarantee for each subscription.
First, declare a new topic:
var Invoices = ftl.Topic[Invoice]("invoices")
Then declare each subscription on the topic:
var _ = ftl.Subscription(Invoices, "emailInvoices")
And finally define a Sink to consume from the subscription:
//ftl:subscribe emailInvoices
func SendInvoiceEmail(ctx context.Context, in Invoice) error {
// ...
}
Events can be published to a topic like so:
Invoices.Publish(ctx, Invoice{...})
First, declare a new topic :
@Export
@TopicDefinition("invoices")
internal interface InvoiceTopic : Topic<Invoice>
Events can be published to a topic by injecting it into an @Verb
method:
@Verb
fun publishInvoice(request: InvoiceRequest, topic: InvoiceTopic) {
topic.publish(Invoice(request.getInvoiceNo()))
}
There are two ways to subscribe to a topic. The first is to declare a method with the @Subscription
annotation, this is generally used when
subscribing to a topic inside the same module:
@Subscription(topic = "invoices", name = "invoicesSubscription")
fun consumeInvoice(event: Invoice) {
// ...
}
This is ok, but it requires the use of string constants for the topic name, which can be error-prone. If you are subscribing to a topic from another module, FTL will generate a type-safe subscription meta annotation you can use to subscribe to the topic:
@Subscription(topic = "invoices", module = "publisher", name = "invoicesSubscription")
annotation class InvoicesSubscription
This annotation can then be used to subscribe to the topic:
@InvoicesSubscription
fun consumeInvoice(event: Invoice) {
// ...
}
Note that if you want multiple subscriptions or control over the subscription name you will need to use the @Subscription
annotation.
First, declare a new topic:
@Export
@TopicDefinition("invoices")
interface InvoiceTopic extends Topic<Invoice> {}
Events can be published to a topic by injecting it into an @Verb
method:
@Verb
void publishInvoice(InvoiceRequest request, InvoiceTopic topic) throws Exception {
topic.publish(new Invoice(request.getInvoiceNo()));
}
There are two ways to subscribe to a topic. The first is to declare a method with the @Subscription
annotation, this is generally used when
subscribing to a topic inside the same module:
@Subscription(topicClass = InvoiceTopic.class, name = "invoicesSubscription")
public void consumeInvoice(Invoice event) {
// ...
}
If you are subscribing to a topic from another module, FTL will generate a type-safe subscription meta annotation you can use to subscribe to the topic:
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Subscription(
topic = "invoices",
module = "publisher",
name = "invoicesSubscription"
)
public @interface InvoicesSubscription {
}
This annotation can then be used to subscribe to the topic:
@InvoicesSubscription
public void consumeInvoice(Invoice event) {
// ...
}
Note that if you want multiple subscriptions or control over the subscription name you will need to use the @Subscription
annotation.
NOTE! PubSub topics cannot be published to from outside the module that declared them, they can only be subscribed to. That is, if a topic is declared in module
A
, moduleB
cannot publish to it.