Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 0 additions & 133 deletions docs/06-concepts/14-scheduling.md

This file was deleted.

103 changes: 103 additions & 0 deletions docs/06-concepts/14-scheduling/01-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Setup

Serverpod supports scheduling future work with the `future call` feature. Future calls are calls that will be invoked at a later time. An example is if you want to send a drip-email campaign after a user signs up. You can schedule a future call for a day, a week, a month, or a [recurring interval](recurring-task). The calls are stored in the database, so they will persist even if the server is restarted.

A future call is guaranteed to only execute once across all your instances that are running, but execution failures are not handled automatically. It is your responsibility to schedule a new future call if the work was not able to complete.

To create future calls, extend the `FutureCall` class and define the methods you wish to invoke at a later time.

```dart
import 'package:serverpod/serverpod.dart';

class ExampleFutureCall extends FutureCall {
Future<void> doWork(Session session, String data) async {
// Do something interesting in the future here.
}

Future<void> doOtherWork(Session session, String data) async {
// Do something interesting in the future here.
}
}
```

:::info
For a method to be recognized by Serverpod as a future call, it must return a `Future<void>` and take at least two parameters. The first parameter must be a [`Session`](../sessions) object. You can pass any serializable types as other parameters, and even use `List`, `Map`, `Set` or Dart records as long as they are typed. `Streaming` parameters are not supported.
:::

Next, you need to generate the code for your future calls:

```bash
$ serverpod generate
```

`serverpod generate` will create a type-safe interface for invoking the future calls in the server's `generated/future_calls.dart` file. This interface can be accessed from the Serverpod object.

The future calls you create are registered by `Serverpod` after the server starts.

```dart
import 'package:serverpod/serverpod.dart';
import 'package:serverpod_auth_idp_server/core.dart';

import 'src/generated/protocol.dart';
import 'src/generated/endpoints.dart';

void run(List<String> args) async {
final pod = Serverpod(
args,
Protocol(),
Endpoints(),
);

await pod.start();
}
```

You are now able to schedule future calls to be invoked in the future by calling either `callWithDelay` or `callAtTime` depending on your needs.

:::warning
Scheduling a future call before the server starts will lead to exceptions.
:::

Invoke a future call 1 hour from now by calling `callWithDelay`.

```dart
await pod.futureCalls
.callWithDelay(const Duration(hours: 1))
.example
.doWork('1');
```

Invoke a future call at a specific time and/or date in the future by calling `callAtTime`.

```dart
await pod.futureCalls
.callAtTime(DateTime(2026, 1, 1))
.example
.doOtherWork('2');
```

:::info
Scheduling a future call at a specific time/date will always resolve the `DateTime` to UTC.
:::

When scheduling a future call, it is also possible to give it an `identifier` so that it can be referenced later. The same identifier can be applied to multiple future calls.

```dart
await pod.futureCalls
.callWithDelay(
const Duration(hours: 1),
identifier: 'an-identifying-string',
)
.example
.doWork('1');
```

This identifier can then be used to cancel all future calls scheduled with said identifier.

```dart
await pod.futureCalls.cancel('an-identifying-string');
```

:::info
The future call feature is not enabled when running Serverpod in serverless mode.
:::
71 changes: 71 additions & 0 deletions docs/06-concepts/14-scheduling/02-recurring-task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Recurring Task

The recommended way to achieve cron-like scheduling is by scheduling a future call inside another.
To set this up, extend the `FutureCall` class and define two methods.

```dart
import 'package:serverpod/serverpod.dart';

class ExampleFutureCall extends FutureCall {
Future<void> doWork(Session session, int input) async {
await _doWork(session, input);
}

Future<void> _doWork(Session session, int input) async {
session.log('Working with input $input');
}
}
```

Next, generate the code for your future call:

```bash
$ serverpod generate
```

:::info
Code is only generated for the public method while the private method contains the logic to be invoked as a recurring task.
:::

Next, import the generated `endpoints.dart` file and schedule the recurring future call using the generated code:

```dart
import 'package:serverpod/serverpod.dart';
import 'generated/endpoints.dart';

class ExampleFutureCall extends FutureCall {
Future<void> doWork(Session session, int input) async {
await session.serverpod.futureCalls
.callWithDelay(const Duration(minutes: 20))
.example
.doWork(input + 1);

await _doWork(session, input);
}

Future<void> _doWork(Session session, int input) async {
session.log('Working with input $input');
}
}
```

Now when you schedule the `doWork` future call, it will continously invoke `_doWork` at an interval of 20 minutes.

```dart
import 'package:serverpod/serverpod.dart';
import 'package:serverpod_auth_idp_server/core.dart';

import 'src/generated/protocol.dart';
import 'src/generated/endpoints.dart';

void run(List<String> args) async {
final pod = Serverpod(
args,
Protocol(),
Endpoints(),
);

await pod.start();
await pod.futureCalls.callWithDelay(Duration(minutes: 20)).example.doWork(2);
}
```
Loading