Skip to content

Commit

Permalink
fix: adding missing docs and completions (#4074)
Browse files Browse the repository at this point in the history
  • Loading branch information
wesbillman authored Jan 16, 2025
1 parent 6d485fa commit 275cf7f
Show file tree
Hide file tree
Showing 15 changed files with 256 additions and 109 deletions.
44 changes: 44 additions & 0 deletions docs/content/docs/reference/ingress.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,50 @@ Complex query params can also be encoded as JSON using the `@json` query paramet
curl -i http://localhost:8891/users/123/posts/456?@json=%7B%22tag%22%3A%22ftl%22%7D
```

<!-- kotlin -->
Kotlin uses the `@Ingress` annotation to define HTTP endpoints. These endpoints will be exposed on the default ingress port (local development defaults to `http://localhost:8891`).

```kotlin
import xyz.block.ftl.Ingress
import xyz.block.ftl.Option

// Simple GET endpoint with path and query parameters
@Ingress("GET /users/{userId}/posts")
fun getPost(request: Request): Response {
val userId = request.pathParams["userId"]
val postId = request.queryParams["postId"]
return Response.ok(Post(userId, postId))
}

// POST endpoint with request body
@Ingress("POST /users/{userId}/posts")
fun createPost(request: Request): Response {
val userId = request.pathParams["userId"]
val body = request.body<PostBody>()
return Response.created(Post(userId, body.title))
}

// Request body data class
data class PostBody(
val title: String,
val content: String,
val tag: Option<String> // Optional field using Option type
)

// Response data class
data class Post(
val userId: String,
val title: String
)
```

Key features:
- The `@Ingress` annotation takes a string parameter combining the HTTP method and path
- Path parameters are accessed via `request.pathParams`
- Query parameters are accessed via `request.queryParams`
- Request bodies can be automatically deserialized using `request.body<T>()`
- Optional fields are represented using the `Option<T>` type
- Response helpers like `Response.ok()` and `Response.created()` for common status codes

<!-- java -->

Expand Down
21 changes: 14 additions & 7 deletions docs/content/docs/reference/secretsconfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,19 @@ Configuration values are named, typed values. They are managed by the `ftl confi

<!-- go -->


To declare a configuration value use the following syntax:

```go
// Simple string configuration
type ApiUrl = ftl.Config[string]

// Type-safe configuration
type DefaultUser = ftl.Config[Username]
```

Note that the name of the configuration value as represented in the FTL schema is the lower camel case version of the type name.
Note that the name of the configuration value as represented in the FTL schema is the lower camel case version of the type name (e.g., `ApiUrl` becomes `apiUrl`).

Configuration values can be injected into FTL methods, such as `@Verb`, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:
Configuration values can be injected into FTL methods, such as //ftl:verb, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:

```go
//ftl:verb
Expand Down Expand Up @@ -76,12 +79,16 @@ Secrets are encrypted, named, typed values. They are managed by the `ftl secret`
Declare a secret with the following:

```go
// Simple string secret
type ApiToken = ftl.Secret[string]

// Type-safe secret
type ApiKey = ftl.Secret[Credentials]
```

Like configuration values, the name of the secret as represented in the FTL schema is the lower camel case version of the type name.
Like configuration values, the name of the secret as represented in the FTL schema is the lower camel case version of the type name (e.g., `ApiToken` becomes `apiToken`).

Configuration values can be injected into FTL methods, such as `@Verb`, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:
Secrets can be injected into FTL methods, such as //ftl:verb, HTTP ingress, Cron etc. To inject a secret value, use the following syntax:

```go
//ftl:verb
Expand All @@ -93,7 +100,7 @@ func CallApi(ctx context.Context, req Request, apiKey ApiKey) error {

<!-- kotlin -->

Configuration values can be injected into FTL methods, such as `@Verb`, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:
Secrets can be injected into FTL methods, such as `@Verb`, HTTP ingress, Cron etc. To inject a secret value, use the following syntax:

```kotlin
@Export
Expand All @@ -103,7 +110,7 @@ fun hello(helloRequest: HelloRequest, @Secret("apiKey") apiKey: String): HelloRe
}
```
<!-- java -->
Configuration values can be injected into FTL methods, such as `@Verb`, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:
Secrets can be injected into FTL methods, such as `@Verb`, HTTP ingress, Cron etc. To inject a secret value, use the following syntax:

```java
@Export
Expand Down
44 changes: 44 additions & 0 deletions docs/content/docs/reference/verbs.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,27 @@ fun echo(request: EchoRequest): EchoResponse {
}
```

<!-- java -->
To declare a Verb, write a normal Java method with the following signature, annotated with the `@Verb` annotation:

```java
@Verb
public Output f(Input input) { }
```

eg.

```java
public class EchoRequest {}

public class EchoResponse {}

@Verb
public EchoResponse echo(EchoRequest request) {
// ...
}
```

{% end %}

By default verbs are only [visible](../visibility) to other verbs in the same module.
Expand Down Expand Up @@ -103,4 +124,27 @@ interface TimeClient {
fun call(): TimeResponse
}
```

<!-- java -->
To call a verb, import the module's verb client, add it to your verb's signature, then call it. eg.

```java
import ftl.time.TimeClient;

@Verb
public EchoResponse echo(EchoRequest request, TimeClient time) {
TimeResponse response = time.call();
// ...
}
```

Verb clients are generated by FTL. If the callee verb belongs to the same module as the caller, you must manually define your
own client:

```java
@VerbClient(name="time")
public interface TimeClient {
TimeResponse call();
}
```
{% end %}
1 change: 1 addition & 0 deletions frontend/vscode/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export class FTLClient {
documentSelector: [
{ scheme: 'file', language: 'kotlin' },
{ scheme: 'file', language: 'go' },
{ scheme: 'file', language: 'java' },
],
outputChannel: this.outputChannel,
}
Expand Down
2 changes: 1 addition & 1 deletion internal/lsp/hoveritems.go

Large diffs are not rendered by default.

36 changes: 29 additions & 7 deletions internal/lsp/markdown/completion/go/retry.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
Directive for retrying an async operation.

Any verb called asynchronously (specifically, PubSub subscribers and cron jobs) may specify a basic exponential backoff retry policy.
Any verb called asynchronously (specifically, PubSub subscribers and cron jobs) may specify a basic exponential backoff retry policy. You can optionally specify a catch verb to handle final failures.

```go
// Basic retry
//ftl:retry 10 5s 1m
func Process(ctx context.Context, in Invoice) error {
// Process with retries
return nil
func processPayment(ctx context.Context, payment Payment) error {
// Process with retries
return nil
}

// Retry with catch handler
//ftl:retry 5 1s catch recoverPaymentProcessing
func processPayment(ctx context.Context, payment Payment) error {
// Process with retries, failures will be sent to recoverPaymentProcessing verb
return nil
}

// The catch verb that handles final failures
//ftl:verb
func recoverPaymentProcessing(ctx context.Context, request builtin.CatchRequest[Payment]) error {
// Safely handle final failure of the payment
return nil
}
```

See https://block.github.io/ftl/docs/reference/retries/
---

//ftl:retry ${1:attempts} ${2:minBackoff} ${3:maxBackoff}
func ${4:Process}(ctx context.Context, in ${5:Type}) error {
${6:// TODO: Implement}
//ftl:retry ${1:attempts} ${2:minBackoff} ${3:maxBackoff}${4: catch ${5:catchVerb}}
func ${6:process}(ctx context.Context, in ${7:Type}) error {
${8:// TODO: Implement}
return nil
}

// Optional catch verb handler
//ftl:verb
func ${5:catchVerb}(ctx context.Context, request builtin.CatchRequest[${7:Type}]) error {
${9:// Safely handle final failure}
return nil
}
32 changes: 0 additions & 32 deletions internal/lsp/markdown/completion/go/retryWithCatch.md

This file was deleted.

24 changes: 6 additions & 18 deletions internal/lsp/markdown/completion/java/config.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,15 @@
Declare a config variable.
Inject a configuration value into a method.

Configuration values are named, typed values. They are managed by the `ftl config` command-line.
Configuration values can be injected into FTL methods such as @Verb, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:

```java
// Will create a config value called "myConfig" in the FTL schema
@Config
public class MyConfig {
private String value;

public String getValue() {
return value;
}
@Verb
HelloResponse hello(HelloRequest helloRequest, @Config("defaultUser") String defaultUser) {
return new HelloResponse("Hello, " + defaultUser);
}
```

See https://block.github.io/ftl/docs/reference/secretsconfig/
---

@Config
public class ${1:Name} {
private ${2:Type} value;

public ${2:Type} getValue() {
return value;
}
}
@Config("${5:configName}")
8 changes: 3 additions & 5 deletions internal/lsp/markdown/completion/java/cron.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ class MyCron {
See https://block.github.io/ftl/docs/reference/cron/
---

class ${1:Name} {
@Cron("${2:schedule}")
void ${3:name}() {
${4:// Add your cron job logic here}
}
@Cron("${1:schedule}")
void ${2:name}() {
${3:// Add your cron job logic here}
}
35 changes: 25 additions & 10 deletions internal/lsp/markdown/completion/java/retry.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
Directive for retrying an async operation.

Any verb called asynchronously (specifically, PubSub subscribers and cron jobs) may specify a basic exponential backoff retry policy.
Any verb called asynchronously (specifically, PubSub subscribers and cron jobs) may specify a basic exponential backoff retry policy. You can optionally specify a catch verb to handle final failures.

```java
// Basic retry
@Retry(attempts = 10, minBackoff = "5s", maxBackoff = "1m")
public class InvoiceProcessor {
public void process(Context ctx, Invoice invoice) throws Exception {
// Process with retries
}
public void processPayment(Payment payment) throws Exception {
// Process with retries
}

// Retry with catch handler
@Retry(attempts = 5, minBackoff = "1s", catchVerb = "recoverPaymentProcessing")
public void processPayment(Payment payment) throws Exception {
// Process with retries, failures will be sent to recoverPaymentProcessing verb
}

// The catch verb that handles final failures
@Verb
public void recoverPaymentProcessing(CatchRequest<Payment> req) {
// Safely handle final failure of the payment
}
```

See https://block.github.io/ftl/docs/reference/retries/
---

@Retry(attempts = ${1:10}, minBackoff = "${2:5s}", maxBackoff = "${3:1m}")
public class ${4:Processor} {
public void ${5:process}(Context ctx, ${6:Type} input) throws Exception {
${7:// TODO: Implement}
}
@Retry(attempts = ${1:10}, minBackoff = "${2:5s}", maxBackoff = "${3:1m}"${4:, catchVerb = "${5:catchVerb}"})
public void ${6:process}(${7:Type} input) throws Exception {
${8:// TODO: Implement}
}

// Optional catch verb handler
@Verb
public void ${5:catchVerb}(CatchRequest<${7:Type}> req) {
${9:// Safely handle final failure}
}
15 changes: 15 additions & 0 deletions internal/lsp/markdown/completion/java/secret.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Inject a secret value into a method.

Secrets are encrypted, named, typed values. They are managed by the `ftl secret` command-line. To inject a secret value, use the following syntax:

```java
@Verb
HelloResponse hello(HelloRequest helloRequest, @Secret("apiKey") String apiKey) {
return new HelloResponse("Hello from API: " + apiKey);
}
```

See https://block.github.io/ftl/docs/reference/secretsconfig/
---

@Secret("${5:secretName}")
Loading

0 comments on commit 275cf7f

Please sign in to comment.