Machinery for blocking http requests in place, except actual networking

This commit is contained in:
2022-05-03 00:36:11 -04:00
parent d28c588468
commit c41d0522df
9 changed files with 381 additions and 80 deletions

View File

@@ -295,6 +295,9 @@ LuaDefine(tangible_scan, "plane,x,y,radius,omit_nowhere",
LuaDefine(wait, "nticks",
"|Wait the specified number of ticks.") {
World *w = World::fetch_global_pointer(L);
w->guard_blockable(L, "wait");
// Parse the argument.
LuaArg seconds;
LuaStack LS(L, seconds);
int64_t n = LS.ckinteger(seconds);
@@ -302,30 +305,19 @@ LuaDefine(wait, "nticks",
luaL_error(L, "Argument to wait must be between 0 and 1000000");
return LS.result();
}
if (!lua_isyieldable(L)) {
// in a probe, wait throws an error.
luaL_error(L, "cannot wait in a probe.");
return LS.result();
} else if (!w->is_authoritative()) {
// in a nonauth model, yield is converted to nopredict.
lua_yield(L, 0);
return LS.result();
} else {
// in an authoritative model, wait schedules a continuation.
w->schedule(w->clock_ + n, w->lthread_thread_id_, w->lthread_place_id_);
lua_yield(L, 0);
return LS.result();
}
// Schedule a continuation.
w->schedule(w->clock_ + n, w->lthread_thread_id_, w->lthread_place_id_);
return lua_yield(L, 0);
}
LuaDefine(nopredict, "",
"|Stop predictive execution of this thread.") {
if (lua_gettop(L) != 0) {
luaL_error(L, "tangible.nopredict takes no arguments");
}
World *w = World::fetch_global_pointer(L);
if (lua_isyieldable(L) && !w->is_authoritative()) {
return lua_yield(L, 0);
w->guard_nopredict(L, "nopredict");
if (lua_gettop(L) != 0) {
luaL_error(L, "nopredict takes no arguments");
}
return 0;
}
@@ -529,4 +521,36 @@ LuaDefine(doc, "function",
}
(*ostream) << doc;
return LS.result();
}
LuaDefine(http_get, "request",
"|Make an HTTP GET request. Returns an HTTP response."
"|See doc(http.request) and doc(http.response).") {
World *w = World::fetch_global_pointer(L);
w->guard_blockable(L, "http.get");
LuaArg request;
LuaRet response;
LuaStack LS(L, request, response);
HttpOutRequest req;
// Parse the request and make sure it's valid.
req.set_config(LS, request);
req.set_defaults();
eng::string error = req.check();
if (!error.empty()) {
HttpInResponse::store_fail(LS, response, 400, util::ss("bad request: ", error));
return LS.result();
}
// Give the request an ID.
req.set_request_id(w->id_global_pool_.get_one());
req.set_place_id(w->lthread_place_id_);
req.set_thread_id(w->lthread_thread_id_);
// Store it in the global request table.
w->http_requests_[req.request_id()] = req;
// Block.
return lua_yield(L, 0);
}