In this page
GreyCat Server
Introduction
To empower digital twin, GreyCat is not only a Runtime but also a Server.
Any function can be exposed to remote procedure call (RPC) by adding an @expose pragma
@expose
fn compute(p: int): int {
return 3 + 5 + p;
}
fn main() {
println(compute(2));
}
This minimal code snippet already defines a server (–user=1 deactivates security, more on this later)
greycat serve --user=1
# 10
# INFO 2023-05-25T08:34:21.719127+00:00 GreyCat is serving on port: 8080
# WARN 2023-05-25T08:34:21.719174+00:00 Impersonate mode with user 1
GreyCat server can be queried through an HTTP API.
The parameters for the endpoint can be url encoded:
curl -X POST -d "[100]" http://localhost:8080/project::compute
> 108
Or the parameters for the endpoint can be JSON encoded:
curl -X POST --json "[100]" http://localhost:8080/project::compute
> 108
Functions and error handling
fn sub_process() {
throw "stop here";
}
@expose
fn computeWithSub(p: int): int {
sub_process();
return 3 + 5 + p;
}
fn main() {
var res = compute(2);
println(res);
}
In this example sub_process and compute share the error handling management, leading to the following error stack
greycat run
{
"_type": "core.Error",
"code": { "_type": "core.ErrorCode", "field": "throw" },
"value": "stop here",
"stack": [
"sub_process (project.gcl:65:23)",
"compute (project.gcl:69:18)",
"main (project.gcl:73:26)"
]
}
Function entrypoint == Transaction
Every exception thrown activates a rollback mechanism, leaving the temporal graph unchanged
var counter: node<int?>;
@expose
fn inc_count() {
println(*counter);
counter.set((counter.resolve() ?? 0) + 1);
throw "my bad";
}
This is illustrated in this example, where many calls do not alter the counter due to the following exception
greycat run inc_count
# null
# {"_type":"core.Error","code":{"_type":"core.ErrorCode","field":"throw"},"value":"my bad","stack":["inc_count (project.gcl:70:20)"]}
greycat run inc_count
# null
# {"_type":"core.Error","code":{"_type":"core.ErrorCode","field":"throw"},"value":"my bad","stack":["inc_count (project.gcl:70:20)"]}
Exposed functions are for short computation!
As many API oriented framework, GreyCat adds a timeout to remote function calls (default of 30s, configurable)
@expose
fn heavy_computation() {
while (true) {
// noop
}
}
any call through HTTP API will then result in a timeout exception (therefore rollback)
greycat serve --user=1
curl -X POST http://localhost:8080/project/heavy_computation
# {"_type":"core.Error","code":{"_type":"core.ErrorCode","field":"timeout"},"stack":["heavy_computation (project.gcl:67:15)"]}
timeout is similar for write and read function entrypoint, this enhances the server against multi-user experience
Long running functions? Task is the answer!
An in depth explanation can be found here
Env variables
GreyCat supports a wide range of environment variables that can either be defined on the cli or in an .env file
| Command-Line Option | Environment Variable | Description |
|---|---|---|
| –log= |
GREYCAT_LOG=info | Level of log (none,error,warn,info trace) |
| –logfile | GREYCAT_LOGFILE=false | Create a logfile |
| –cache= |
GREYCAT_CACHE=8192 | Size of cache in MB |
| –store= |
GREYCAT_STORE=10240 | Size of store in MB |
| –http_threads= |
GREYCAT_HTTP_THREADS=3 | Number of workers dedicated to handle http connections |
| –req_workers= |
GREYCAT_REQ_WORKERS=2 | Number of workers dedicated to handle RPC requests |
| –workers= |
GREYCAT_WORKERS=1 | Number of workers dedicated to handle GreyCat async tasks |
| –port= |
GREYCAT_PORT=8080 | Port used by serve command |
| –webroot= |
GREYCAT_WEBROOT=dist | Webroot to serve |
| –key= |
GREYCAT_KEY=(null) | Path to private key |
| –keysafe= |
GREYCAT_KEYSAFE=(null) | Pass for user pass |
| –user= |
GREYCAT_USER=0 | Impersonate mode to serve or run using a user id |
| –tz= |
GREYCAT_TZ=(null) | Configure local timezone (see https://www.iana.org/time-zones, ex: Europe/Luxembourg) |
| –validity= |
GREYCAT_VALIDITY=86400 | Validity of connection cookie (in s) |
| –unsecure | GREYCAT_UNSECURE=false | Allows GreyCat tokens to be used behind an unsecure reverse-proxy (aka http) |
| –task_pool_capacity= |
GREYCAT_TASK_POOL_CAPACITY=10000 | Number of waiting task capacity |
| –request_pool_capacity= |
GREYCAT_REQUEST_POOL_CAPACITY=128 | Number of waiting task capacity |
| –oid_public_key= |
GREYCAT_OID_PUBLIC_KEY=(null) | Keycloak public key used to sign login tokens |
| –oid_client_id= |
GREYCAT_OID_CLIENT_ID=(null) | Keycloak client id to use for connection |
| –oid_config_url= |
GREYCAT_OID_CONFIG_URL=(null) | URL to retrieve the OpenID configuration object. Ex with Azure: https://login.microsoftonline.com/{TENANT_ID}/v2.0/.well-known/openid-configuration |
| –oid_keys_url= |
GREYCAT_OID_KEYS_URL=(null) | OpenID keys discovery URL |
| –mode= |
GREYCAT_MODE=(null) | Default mode (serve,run) |
| –keep_alive | GREYCAT_KEEP_ALIVE=false | Enable keep alive ability for server |
| –app_name= |
GREYCAT_APP_NAME=(null) | Application name, must be unique within user environment |
Runtime info
The runtime module provides a RuntimeInfo object which contains all important information about the currently running GreyCat server
| Name | Type | Description |
|---|---|---|
| version | String | GreyCat version |
| program_version | String? | |
| arch | String | |
| timezone | TimeZone | env specified tz else machine tz |
| license | License | |
| io_threads | int | |
| bg_threads | int | |
| fg_threads | int | |
| mem_total | int | |
| mem_worker | int | |
| nb_ctx | int | |
| store_stats | StoreStat? |
Store Stat
| Name | Type | Description |
|---|---|---|
| capacity_bytes | int | |
| allocated_bytes | int | |
| allocated_ratio | float | |
| remained_bytes | int | |
| remained_ratio | float | |
| used_bytes | int | |
| used_ratio | float | |
| available_bytes | int | |
| available_ratio | float |