PubSub

FTL has first-class support for PubSub, modelled on the concepts of topics (where events are sent) and subscribers (a verb which consumes events). Subscribers are, as you would expect, sinks. Each subscriber is a cursor over the topic it is associated with. Each topic may have multiple subscriptions. Each published event has an at least once delivery guarantee for each subscription.

First, declare a new topic:

package payments

type Invoices = ftl.TopicHandle[Invoice, ftl.SinglePartitionMap[Invoice]]

Note that the name of the topic as represented in the FTL schema is the lower camel case version of the type name.

The Invoices type is a handle to the topic. It is a generic type that takes two arguments: the event type and the partition map type. The partition map type is used to map events to partitions. In this case, we are using a single partition map, which means that all events are sent to the same partition.

Then define a Sink to consume from the topic:

//ftl:subscribe payments.invoices from=beginning
func SendInvoiceEmail(ctx context.Context, in Invoice) error {
  // ...
}

Events can be published to a topic by injecting the topic type into a verb:

func PublishInvoice(ctx context.Context, topic Invoices) error {
   topic.Publish(ctx, Invoice{...})
   // ...
}

First, declare a new topic :

@Export
@Topic("invoices")
internal interface InvoiceTopic : WriteableTopic<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()))
}

To subscribe to a topic use the @Subscription annotation, referencing the topic class and providing a method to consume the event:

@Subscription(topic = InvoiceTopic::class, from = FromOffset.LATEST)
fun consumeInvoice(event: Invoice) {
    // ...
}

If you are subscribing to a topic from another module, FTL will generate a topic class for you so you can subscribe to it. This generated topic cannot be published to, only subscribed to:

@Topic(name="invoices", module="publisher")
internal interface InvoiceTopic : ConsumableTopic<Invoice>

First, declare a new topic:

@Export
@Topic("invoices")
interface InvoiceTopic extends WriteableTopic<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()));
}

To subscribe to a topic use the @Subscription annotation, referencing the topic class and providing a method to consume the event:

@Subscription(topic = InvoiceTopic.class, from = FromOffset.LATEST)
public void consumeInvoice(Invoice event) {
    // ...
}

If you are subscribing to a topic from another module, FTL will generate a topic class for you so you can subscribe to it. This generated topic cannot be published to, only subscribed to:

@Topic(name="invoices", module="publisher")
 interface InvoiceTopic extends ConsumableTopic<Invoice> {}

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, module B cannot publish to it.