-
Notifications
You must be signed in to change notification settings - Fork 77
docs: Type-safe code generated interface for future calls #390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@marcelomendoncasoares here's the PR for the future calls docs |
marcelomendoncasoares
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick PR on the docs, @Crazelu! I have left a few guidelines about the experience we aim with docs on the comments, and also some improvement/fixes suggestions.
Beyond these, I missed a reference on the usage of abstract to declare future calls in modules, that users can extend in their own projects - since there is no way for users to mixture the ones generated in the module with their own. We should also present the support for inheritance of future calls in itself.
Another extra page that is worth adding is Recurring tasks to show how to achieve a cron-like scheduling. The current recommended way is by scheduling a future call inside another - at the start, for example. With generated future calls, though, it will probably be a two step operation or require the creation of two separate future calls: one for the unit execution, the other for invoking the first twice (now and next) to make it recurrent.
| 3. __Avoid changing or removing fields and types in the serialized classes.__ However, you are free to add new fields as long as they are nullable. | ||
| 4. __Avoid changing parameter names in future call methods.__ Changing the parameter names of the future call methods will break backward compatibility since parameters are passed by name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Unrelated change, but it is worth for future calls (and only valid now with a recent PR).
| 3. __Avoid changing or removing fields and types in the serialized classes.__ However, you are free to add new fields as long as they are nullable. | |
| 4. __Avoid changing parameter names in future call methods.__ Changing the parameter names of the future call methods will break backward compatibility since parameters are passed by name. | |
| 3. __Avoid changing or removing fields and types in the serialized classes.__ However, you are free to add new fields as long as they are nullable or have a default value. | |
| 4. __Avoid changing parameter names in future call methods.__ Changing the parameter names of the future call methods will break backward compatibility since parameters are passed by name. |
| @@ -1,92 +1,16 @@ | |||
| # Scheduling | |||
| # Overview | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The experience we want to provide with the docs is for users to receive as little context as they need to get started with a given feature, then be redirected to dedicated pages as needed to get deeper in details or more advanced scenarios. The "Working with Endpoints" and "Working with Models" pages are not examples here, because they are presenting everything at once and have a refactor pending. Take an inspiration on how we did the Authentication and each Provider under it.
Future calls are different from authentication, though, because they require no setup to work - as with models and endpoints. Although there is the possibility to configure, this is optional and should be shown separately.
This overview page should start with the general context (as it has now) and proceed guiding the user on how to create a simple FutureCall. Think of this first page more like a guide than a documentation. Then, all details that could be mentioned along the way can be noted in infos/tips/notes that point to the more advanced page.
It is worth mentioning in the feature presentation as it being the same experience as endpoints, but for scheduling future work.
| ```dart | ||
| void run(List<String> args) async { | ||
| final pod = Serverpod( | ||
| args, | ||
| Protocol(), | ||
| Endpoints(), | ||
| ); | ||
| ... | ||
| await pod.start(); | ||
| ... | ||
| } | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is best that the first examples are fully complete snippets that can be copy/pasted and work (or nearly due to the name of the project that goes in the imports). See the example below from authentication:
serverpod_docs/docs/06-concepts/11-authentication/01-setup.md
Lines 29 to 61 in 4367b7e
| ```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(), | |
| ); | |
| // Set up authentication services | |
| // The `pod.getPassword()` will get the value from `config/passwords.yaml`. | |
| pod.initializeAuthServices( | |
| tokenManagerBuilders: [ | |
| JwtConfig( | |
| // Pepper used to hash the refresh token secret. | |
| refreshTokenHashPepper: pod.getPassword('jwtRefreshTokenHashPepper')!, | |
| // Algorithm used to sign the tokens (`hmacSha512` or `ecdsaSha512`). | |
| algorithm: JwtAlgorithm.hmacSha512( | |
| // Private key to sign the tokens. Must be a valid HMAC SHA-512 key. | |
| SecretKey(pod.getPassword('jwtHmacSha512PrivateKey')!), | |
| ) | |
| ), | |
| ], | |
| ); | |
| await pod.start(); | |
| } | |
| ``` |
| Next, you need to generate the code for your future calls. You do this by running `serverpod generate` in the server directory of your project: | ||
|
|
||
| ```bash | ||
| $ cd your_server | ||
| $ 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is no longer necessary to cd into the server to run generate.
| Next, you need to generate the code for your future calls. You do this by running `serverpod generate` in the server directory of your project: | |
| ```bash | |
| $ cd your_server | |
| $ 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. | |
| Next, you need to generate the code for your future calls: | |
| \```bash | |
| $ serverpod generate | |
| \``` | |
| Running 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 through the `pod.futureCalls` getter. |
Ignore the backslash before the ``` markers. This is just to avoid breaking the suggestion.
| @@ -0,0 +1,75 @@ | |||
| # Legacy | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is worth explaining why is this format legacy and in favor of what has it is been discontinued - citing the need for manual registration and the error-prone management of future calls by string names. It is good to have a warning pointing to the overview as the new recommended experience to highlight this.
| ``` | ||
|
|
||
| :::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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer true: methods can now have an arbitrary number of parameters, including only the session, right? We should also mention here that Streaming parameters are not supported.
| Future<void> doWork(Session session, String data) async { | ||
| // Do something interesting in the future here. | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to broaden the examples, it could be good to have two methods here and show one with callAtTime and the other with callWithDelay below.
|
|
||
| `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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is worth enforcing with a warning that trying to schedule future calls before server start will lead to exceptions.
Adds documentation for the type-safe code generated interface for future calls