-
Notifications
You must be signed in to change notification settings - Fork 0
/
kinode.wit
198 lines (160 loc) · 5.57 KB
/
kinode.wit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
package kinode:[email protected];
interface standard {
//
// System types:
//
// JSON is passed over WASM boundary as a string.
type json = string;
type node-id = string;
// Context, like a message body, is a protocol-defined serialized byte
// array. It is used when building a Request to save information that
// will not be part of a Response, in order to more easily handle
// ("contextualize") that Response.
type context = list<u8>;
record process-id {
process-name: string,
package-name: string,
publisher-node: node-id,
}
record address {
node: node-id,
process: process-id,
}
record lazy-load-blob {
mime: option<string>,
bytes: list<u8>,
}
record request {
// set in order to inherit lazy-load-blob from parent message, and if
// expects-response is none, direct response to source of parent.
// also carries forward certain aspects of parent message in kernel,
// see documentation for formal spec and examples.
inherit: bool,
// if some, request expects a response in the given number of seconds
expects-response: option<u64>,
body: list<u8>,
metadata: option<json>,
capabilities: list<capability>,
// to grab lazy-load-blob, use get_blob()
}
record response {
inherit: bool,
body: list<u8>,
metadata: option<json>,
capabilities: list<capability>,
// to grab lazy-load-blob, use get_blob()
}
// A message can be a request or a response. within a response, there is
// a result which surfaces any error that happened because of a request.
// A successful response will contain the context of the request it
// matches, if any was set.
variant message {
request(request),
response(tuple<response, option<context>>),
}
record capability {
issuer: address,
params: json,
}
// On-exit is a setting that determines what happens when a process
// panics, completes, or otherwise "ends". NOTE: requests should have
// expects-response set to false, will always be set to that by kernel.
variant on-exit {
none,
restart,
requests(list<tuple<address, request, option<lazy-load-blob>>>),
}
// Network errors come from trying to send a message to another node.
// A message can fail by timing out, or by the node being entirely
// unreachable (offline). In either case, the message is not delivered
// and the process that sent it receives that message along with any
// assigned context and/or lazy-load-blob, and is free to handle it as it
// sees fit. Note that if the message is a response, the process can
// issue a response again, and it will be directed to the same (remote)
// request as the original.
record send-error {
kind: send-error-kind,
message: message,
lazy-load-blob: option<lazy-load-blob>,
}
enum send-error-kind {
offline,
timeout,
}
enum spawn-error {
name-taken,
no-file-at-path,
// TODO more here?
}
//
// System utils:
//
print-to-terminal: func(verbosity: u8, message: string);
//
// Process management:
//
set-on-exit: func(on-exit: on-exit);
get-on-exit: func() -> on-exit;
get-state: func() -> option<list<u8>>;
set-state: func(bytes: list<u8>);
clear-state: func();
spawn: func(
name: option<string>,
wasm-path: string, // must be located within package's drive
on-exit: on-exit,
request-capabilities: list<capability>,
// note that we are restricting granting to just messaging the
// newly spawned process
grant-capabilities: list<process-id>,
public: bool
) -> result<process-id, spawn-error>;
//
// Capabilities management:
//
// Saves the capabilities to persisted process state.
save-capabilities: func(caps: list<capability>);
// Deletes the capabilities from persisted process state.
drop-capabilities: func(caps: list<capability>);
// Gets all capabilities from persisted process state.
our-capabilities: func() -> list<capability>;
//
// Message I/O:
//
// Ingest next message when it arrives along with its source.
// Almost all long-running processes will call this in a loop.
receive: func() ->
result<tuple<address, message>, tuple<send-error, option<context>>>;
// Gets lazy-load-blob, if any, of the message we most recently received.
get-blob: func() -> option<lazy-load-blob>;
// Send message(s) to target(s).
send-request: func(
target: address,
request: request,
context: option<context>,
lazy-load-blob: option<lazy-load-blob>
);
send-requests: func(
requests: list<tuple<address,
request,
option<context>,
option<lazy-load-blob>>>
);
send-response: func(
response: response,
lazy-load-blob: option<lazy-load-blob>
);
// Send a single request, then block (internally) until its response. The
// type returned is Message but will always contain Response.
send-and-await-response: func(
target: address,
request: request,
lazy-load-blob: option<lazy-load-blob>
) -> result<tuple<address, message>, send-error>;
}
world lib {
import standard;
}
world process {
include lib;
export init: func(our: string);
}