書き込みの原子性と同時実行
Nested write(create の中の posts: { create: [...] } など)や、onDelete / onUpdate の Cascade は、1 回の操作で複数のシートに書き込みます。このページでは、こうした操作で何が保証され、何が保証されないかを説明します。
エラー時には何も書かれない
複数シートに書く操作は、内部で書き込みをバッファし、操作全体が成功したときにまとめてシートに書き込みます。途中でエラーになった場合、シートには 1 行も書かれません。
// 子の作成でエラーになる場合
gassma.Users.create({
data: {
id: 4,
name: "Dave",
posts: {
create: [{ id: 4, titel: "..." }], // 列名の誤りでエラー
},
},
});
// → エラー。Users にも Posts にも何も書かれない
これは、Prisma が nested write を暗黙のトランザクションで包むのと同じ保証です。
この保証が及ばないケース
書き込み中にスプレッドシートの API が失敗した場合
バッファをシートに書き出している最中に Google スプレッドシートの API が失敗すると、そこまでの書き込みはシートに残ります。
$transaction を rollback: true(既定)で使うと、書き込み前のバックアップから自動復元されます(詳細は rollback を参照)。
操作中に他のプロセスや人がシートを書き換えた場合
GASsma は、更新・削除する行を位置(行番号)で特定します。対象の行を読んでから書き込むまでの間に、他の誰かが行を挿入・削除すると、意図した行とは別の行に書き込む可能性があります。
GASsma が読んだ時点: 1行目 Alice / 2行目 Bob / 3行目 Carol
→ 「3行目の Carol を更新しよう」
他の誰かが 1行目を削除: 1行目 Bob / 2行目 Carol
GASsma が書き込む: 3行目に書く → そこには誰もいない、あるいは別の行
複数シートに書く操作は、バッファするぶん読んでから書くまでの間隔が長くなります。同時に書き込みが起こる環境では、この点を意識してください。
同時に書き込みが起こりうるなら $transaction で包む
同時に書き込みが起こりうるシステムでは、書き込みを $transaction で包んでください。
gassma.$transaction((tx) => {
tx.Users.create({
data: {
id: 4,
name: "Dave",
posts: {
create: [{ id: 4, title: "Dave の記事", published: true }],
},
},
});
});
$transaction はロックを取得するため、GASsma を経由する書き込みどうしは直列化されます。上の「読んでから書くまで」の割り込みが GASsma の書き込みによって起こることはなくなります。
このロックが直列化するのは GASsma を使う処理どうしだけです。以下には効きません。
- 人がスプレッドシートを手で編集した場合
- GASsma を使っていない別のスクリプトが書き込んだ場合
これらに対しては GASsma からは何もできません。操作中にシートが手編集される可能性がある場合は、そもそも同時に触らない運用にする、編集を受け付けない時間帯に処理するといった、設計側の対処が必要です。