OS7.1.0以降
トランザクションは、応答を待つ問い合わせです。obniz.plugin.send()やcloud.pluginSend()ではデータが一方向に流れるだけですが、トランザクションを使うと、obniz.jsとLuaプラグインが互いに問い合わせて答えを受け取れます。
| 方向 | 問い合わせ | 応答 |
|---|---|---|
| obniz.js → Lua | obniz.plugin.callWait() |
Luaスクリプトのreturnの値 |
| Lua → obniz.js | cloud.transactionWait() |
obniz.plugin.onCloudTransactionの返り値 |
この2つは組み合わせて使えます。callWait()で実行したスクリプトの中から、cloud.transactionWait()でobniz.jsに問い合わせられます。
obniz.plugin.callWait(lua_script, timeout)
端末でLuaスクリプトを実行し、その返り値を待ちます。execLua()はスクリプトを送るだけですが、callWait()はスクリプトがreturnした値を受け取ります。
| 引数 | 型 | 説明 |
|---|---|---|
lua_script |
string | 実行するLuaスクリプトです。 |
timeout |
number | 省略可。結果を待つ時間(ミリ秒)です。デフォルトは30000です。0を指定すると時間の制限なく待ちます。 |
Promiseを返します。
- スクリプトが
returnした最初の値を文字列にしてresolveします。数値は文字列に変換されます。テーブル、boolean、nilなどそれ以外の値は空文字列になるため、JSONなどの文字列に変換してから返してください。 - スクリプトでエラーが起きたとき(Luaのエラーメッセージ付き)、タイムアウトしたとき、端末との接続がリセットされたときはrejectします。
スクリプトはプラグインと同じLuaの環境で動作します。そのため、プラグインのグローバル変数を読み書きしたり、関数を呼んだりできます。
// Luaを実行して返り値を待つ
const result = await obniz.plugin.callWait(`return "hello from lua"`);
console.log(result); // "hello from lua"
// 動作中のプラグインの値を読む
const count = await obniz.plugin.callWait(`return tostring(counter)`);
// Luaでエラーが起きるとPromiseはrejectされる
try {
await obniz.plugin.callWait(`MUST FAILED`);
} catch (e) {
console.log("lua error:", e.message);
}
端末で同時に実行できるcallWait()のスクリプトは、cloud.transactionWait()で待っているものも含めて100個までです。それを超えると、Promiseはbusyでrejectされます。
cloud.transactionWait(data, callback, timeout_ms)
Luaプラグインからobniz.jsへデータを送り、応答を待ちます。
| 引数 | 型 | 説明 |
|---|---|---|
data |
string | obniz.jsへ送るデータです。 |
callback |
function | 省略可。応答を受け取ったとき、またはタイムアウトしたときにcallback(success, result)として呼ばれます。 |
timeout_ms |
number | 省略可。応答を待つ時間(ミリ秒)です。デフォルトは30000です。整数で指定してください。 |
callbackは省略できます。cloud.transactionWait(data, timeout_ms)と書くこともできます。
| 返り値 | 型 | 説明 |
|---|---|---|
success |
boolean | obniz.jsが正常に応答した場合はtrueです。ハンドラがエラーを投げた場合、ハンドラが設定されていない場合、タイムアウトした場合、問い合わせができなかった場合はfalseです。 |
result |
string | nil | obniz.jsからの応答です。ハンドラがエラーを投げた場合はそのメッセージです。タイムアウトの場合はnilです。 |
呼び出せる場所
cloud.transactionWait()は、応答が届くまで実行中のLuaコードを一時停止します。これができるのは、obniz.plugin.callWait()で実行したスクリプトの中だけです。
on_online_loop()やon_command()、起動時に読み込まれるプラグインなど、それ以外の場所で呼んだ場合は待たずに、すぐfalse, nilを返します。
あるスクリプトが応答を待っている間も、プラグインのほかの部分は動き続けます。on_online_loop()などのハンドラは引き続き呼ばれます。タイムアウトの後に届いた応答は無視されます。
-- obniz.plugin.callWait()の中で実行する
local success, result = cloud.transactionWait("get_config", 5000)
if success then
threshold = tonumber(result)
return "updated"
else
return "failed"
end
obniz.plugin.onCloudTransaction
obniz.js側でcloud.transactionWait()に応答するハンドラです。
obniz.plugin.onCloudTransaction = async (data, str) => {
// data: number[] (受信したバイト列), str: 同じデータを文字列にしたもの
return "reply";
};
- ハンドラは
async関数にできます。返したPromiseが完了した時点で応答を送ります。 - 文字列、バイト配列(
number[])、Bufferのいずれかを返してください。何も返さない場合は空文字列を送ります。 - エラーを投げる(またはrejectする)と、Luaには
success = falseが返り、resultにはエラーメッセージが入ります。 - ハンドラが設定されていない場合、obniz.jsはすぐに
success = falseで応答します。そのため、Luaがタイムアウトまで待つことはありません。
Example: 端末からクラウドに問い合わせる
この例では、obniz.jsが端末でスクリプトを実行します。スクリプトはobniz.jsに設定値を問い合わせ、その値を反映して結果を返します。
// プラグインからの問い合わせに答える
obniz.plugin.onCloudTransaction = async (data, str) => {
if (str === "get_interval") {
// 例えば、ここでデータベースや別のAPIから値を読み出す
return "60000";
}
throw new Error(`unknown request: ${str}`);
};
// 問い合わせて答えを待つスクリプトを実行する
const result = await obniz.plugin.callWait(`
local success, value = cloud.transactionWait("get_interval", 5000)
if not success then
return "failed: " .. tostring(value)
end
interval = tonumber(value)
return "interval=" .. value
`);
console.log(result); // "interval=60000"