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 |