# FTL Primitives
This document describes the primitives provided by FTL. These primitives can be composed
# Verbs, sources, and sinks
These are the function primitives of FTL.
## Verbs
Verbs take a single value and return a single value or an error.
```
F(X) -> Y
```
<details>
<summary>Code</summary>
```go
func F(ctx context.Context, x X) (Y, error) {
// ...
}
```
</details>
## Sources
Sources are functions that return a single value and accept no parameters.
Common use cases for sources are providing data from a queue or external system.
```
F() -> Y
```
<details>
<summary>Code</summary>
```go
func F(ctx context.Context) (Y, error) {
// ...
}
```
</details>
## Sinks
Sinks are functions that accept values but return nothing. They will typically
have some side-effect such as delivering to a queue or external system.
```
F(X)
```
<details>
<summary>Code</summary>
```go
func F(ctx context.Context, req X) error {
// ...
}
```
</details>
# Messaging patterns
## Synchronous
A synchronous call to F(X) -> Y executes the function and blocks the caller until the
result or an error is returned.
```
F(X) -> Y
```
<details>
<summary>Code</summary>
```go
func F(ctx context.Context, req X) (Y, error) {
// ...
}
func G(ctx context.Context, x X) (Y, error) {
// Synchronously call another verb.
if y, err := ftl.Call(ctx, F, x); err != nil {
return VerbResponse{}, err
}
// ...
}
```
</details>
## PubSub
PubSub in FTL is comprised of four functions:
1. A (sink) topic T(X) that messages can be published to.
2. One or more (source) subscriptions S^n^() -> X for each topic. Each
subscription is guaranteed to return the next message from the topic.
3. One or more subscribers F^n^(X) for each subscription.
4. A single, optional user-defined function F(E) for handling
failed messages. This may be a dead letter topic.
Other notes:
- A message of type X may be published to a PubSub topic T.
- An arbitrary number of subscriptions can be created for a topic.
- Multiple functions can be configured to consume from a single subscription, first-come first-served.
- FTL PubSub is implemented on top of a Kafka-like event log.
- Different toplogies are just different combinations/configurations of topic retention and subscriptions.
- A subscription is a cursor over the topic's event log.
- Other asynchronous messaging patterns such as callbacks can be implemented on
top of PubSub.
- Batching can be achieved by defining topics/subscribers that accept a slice of X.
<details>
<summary>Code</summary>
Declaring a Topic:
```go
var T = ftl.CreateTopic[X]("topic_x") // Returns a Topic[T]
```
Creating and subscribing to a subscription:
```go
var S = ftl.CreateSubscription(T, "subscription_x", F)
//ftl:sink
func F(ctx context.Context, x X) error {
// ...
}
```
Publishing to a topic
```go
//ftl:verb
func Verb(ctx context.Context, x X) error {
if err := ftl.Publish(ctx, T, x); err != nil {
return Y{}, err
}
// ...
}
```
</details>
### Fanout
In the fanout topology, a copy of each message published to a topic is received
by every subscriber. For this pattern, a separate subscription `Sn` exists for
each subscriber `Fn`:
```
T(X0) ->
S0(X0)
-> F0(X0)
S1(X0)
-> F1(X0)
...
T(X1) ->
S0(X1)
-> F0(X1)
S1(X1)
-> F1(X1)
...
```
<details>
<summary>Code</summary>
```go
var T = ftl.CreateTopic[X]("T")
var S0 = ftl.Subscription(T, "S0", F0)
var S1 = ftl.Subscription(T, "S1", F1)
//ftl:sink
func F0(ctx context.Context, msg T) error {
// ...
}
//ftl:sink
func F1(ctx context.Context, msg T) error {
// ...
}
```
</details>
### First-come first-served
In the first-come first-served topology, a single subscription exists for each
topic and each message published to a topic is sent to the next available
subscriber.
Given a single subscription and two subscribers F0 and F1, this might look like:
```
T(X0) -> S(X0) ->
F0(X0)
```
```
T(X1) ->
S(X1) ->
F1(X1)
```
```
T(X2) ->
S(X2) ->
F1(X2)
```
<details>
<summary>Code</summary>
```go
var T = ftl.CreateTopic[X]("T")
var S = ftl.CreateSubscription(T, "S", F0, F1)
//ftl:sink
func F0(ctx context.Context, msg T) error {
// ...
}
//ftl:sink
func F1(ctx context.Context, msg T) error {
// ...
}
```
</details>