Semantik eksekusi, batasan, dan keamanan

Terakhir diperbarui: 21 Juli 2026

Halaman ini merangkum bagaimana Script berperilaku saat runtime (urutan, transaksi, error, penguncian), batasan statis apa yang dikenakan saat disimpan, dan model keamanannya. Untuk sintaksis, lihat Katalog Statement dan Ekspresi nilai; untuk kombinasi praktis, lihat Cookbook.

Urutan dan mode eksekusi

  • statements dieksekusi secara berurutan dari atas ke bawah. Ketika mencapai Return, eksekusi berhenti di titik tersebut.
  • Sync berjalan pada jalur penanganan permintaan, sedangkan Async berjalan di latar belakang. Ini hanya perbedaan lokasi eksekusi; hasilnya tetap berupa nilai Return di kedua kasus (untuk bentuk respons pemanggilan, lihat Permintaan dan respons di Ikhtisar Script dan Mode eksekusi).
  • Dari kapabilitas ke mode: jika pohon statement mengandung salah satu dari ExternalIo (panggilan eksternal Http), MediaIngest (penyerapan file Media; { source, encoding } di dalam fields.file; berlaku untuk url dan base64), atau LongRunning (Loop berukuran besar, dsb.), maka executionMode dipaksa menjadi Async. Ketiganya merupakan kapabilitas yang terpisah, dan masing-masing dihitung terhadap batas yang berbeda seperti pada Batasan statis di bawah.

Semantik eksekusi

Guard (prakondisi)

Tidak ada statement guard khusus. Anda menyatakannya dengan If dan then:[Return]. Ketika kondisi dilanggar, ia mengembalikan hasil dan tidak menjalankan statement selanjutnya (tentu saja Script tanpa guard juga dimungkinkan).

{ "type": "If", "condition": { "<": [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] },
  "then": [ { "type": "Return", "value": { "ok": false, "reason": "insufficient credit" }, "statusCode": 402 } ] }

Tanpa transaksi dan kompensasi best-effort

Script bukanlah transaksi. Saat gagal, engine mencoba mengompensasi (compensation) pekerjaan yang telah dilakukan sejauh ini dan mengembalikan penyebab error, tetapi dengan keterbatasan berikut (diterima sebagai konsekuensi desain).

  • Membatalkan penghapusan membuat sys.id baru, sehingga referensi yang tadinya menunjuk ke sana menjadi rusak (rollback pembuatan itu mudah; pengubahan memerlukan before-image).
  • Efek eksternal (Http) bersifat ireversibel (panggilan yang sudah keluar beserta biayanya tidak dapat dibatalkan).
  • Saat proses mengalami crash, keadaan yang belum terkompensasi (orphan) dapat tertinggal.

Jika Anda membutuhkan atomisitas sejati, tulis sendiri kompensasi di dalam Script tersebut, atau tempatkan operasi yang tidak dapat dibatalkan (misalnya panggilan eksternal) di paling akhir. Urutan yang paling berbahaya adalah yang "berhasil dirantai tetapi tidak dapat di-rollback, namun tampak aman."

Penguncian optimis

Persaingan update/patch dipersempit dengan version pada ResourceUpdate dan ResourcePatch. Jika Anda memberikan version (ekspresi nilai, Int), pembaruan dilakukan hanya jika cocok dengan sys.version target saat ini; ketidakcocokan di-abort karena error konflik versi (dapat ditangani secara lokal dengan Try/catch). Jika dihilangkan, berlaku last-write-wins tanpa pemeriksaan. Biasanya Anda membaca terlebih dahulu dengan ResourceRead atau ResourcePageRead lalu meneruskan sys.version tersebut (lihat CAS penguncian optimis di Cookbook).

Penulisan berbasis origin

Penulisan selalu tercermin di origin (draft), dan apakah diekspos ke delivery (CDA/ACDA) dikendalikan oleh publish (publish pada ResourceCreate/ResourceUpdate/ResourcePatch, atau ResourcePublish/ResourceUnpublish).

Apa yang dianggap sebagai kegagalan

  • Kegagalan sejati adalah error runtime statement: status akhir Http 400 atau lebih (4xx·5xx; bukan kegagalan jika ignoreStatusCode: true) atau timeout, body respons melebihi 10MiB, atau operasi resource yang gagal (target tidak ada, konflik versi, operasi yang tidak didukung, dsb.). Untuk kegagalan semacam ini engine akan meng-abort dan mengompensasi, dan Anda dapat menanganinya secara lokal dengan Try/catch/finally.
  • Return bukanlah error, melainkan penghentian dini yang normal. Ia bukan target catch (tidak ada konsep user-throw).
  • Di dalam catch, Anda merujuk { message, statement } melalui /error.

Tanpa agregasi sisi server

Tidak ada operasi server khusus untuk count, sum, atau group-by. Anda menghitungnya dengan mengiterasi ResourcePageRead dan menggunakan SetVar/JsonLogic, sehingga terikat pada ukuran fetch dan maxIterations (tidak cocok untuk mengagregasi jutaan record).

Tanpa penungguan atau penundaan

Script tidak memiliki statement Delay. Script dieksekusi sekali lalu selesai, baik pada jalur permintaan (Sync) maupun di latar belakang (Async), dan tidak menunggu atau melakukan polling secara internal hingga job eksternal selesai (hasil Async bersifat terpisah: pemanggil melakukan polling dengan requestId yang diterima dalam 202 untuk memperoleh nilai Return).

Batasan statis (divalidasi saat disimpan)

Berikut ini diperiksa pada saat Script disimpan (pembuatan/perubahan). Jika dilanggar, penyimpanan ditolak (gagal saat penyusunan, bukan saat runtime).

BatasanDefault
Jika ada I/O eksternal, executionMode harus AsyncN/A
Di dalam body Loop, panggilan eksternal Http dan penyerapan file Media dilarangN/A
Panggilan eksternal Http maksimum per definisi3 (maxExternalIo)
SetVar maksimum per definisi (termasuk yang bersarang)5 (maxSetVar)
Total statement maksimum per definisi (termasuk yang bersarang)15 (maxStatements)
Batas atas Http.retry2 (maxHttpRetry)

Batas-batas ini dapat disesuaikan melalui pengaturan server (weegloo.core.script.*) (nilai di atas adalah default).

Penyerapan file Media adalah kapabilitas MediaIngest dan, tidak seperti panggilan eksternal Http (ExternalIo), tidak dihitung terhadap batas maxExternalIo (3). Namun, keharusan Async dan larangan body Loop diterapkan padanya persis seperti pada Http.

Anggaran waktu (runtime)

ModeAnggaran default
Sync10 detik (syncTimeoutMs)
Async60 detik (asyncTimeoutMs)

Batas jumlah per paket

Script adalah resource Billable, dan jumlah per Organization dibatasi oleh paket.

PaketJumlah Script
Free3
Basic10
Pro50
EnterpriseTak terbatas

Ketika batas tercapai, pembuatan Script baru ditolak (jalur yang sama dengan resource Billable lainnya).

Model keamanan

Header secret

Item pada Http.headers yang memiliki secret:true bersifat khusus CMA (administrator): nilainya tidak diekspos ke end-user (ServiceUser) dan hanya didekripsi tepat sebelum dikirim. Simpan rahasia seperti kunci API LLM di sini (bahkan saat dipaketkan menjadi App Bundle, nilai secret tetap disamarkan dan tidak pernah keluar dari Space asalnya).

Identitas eksekusi dan otorisasi

  • Identitas eksekusi: selama eksekusi, setiap operasi resource dilakukan dengan identitas pengguna yang memanggil /execute. createdBy/updatedBy dari resource yang dibuat atau diubah adalah pemanggil, dan cakupan createdBy: ":self" juga diuraikan berdasarkan pemanggil.
  • Ada dua batas otorisasi, dan saat runtime izin resource tidak diperiksa ulang pada setiap statement.
    1. Saat penyusunan (penyimpanan): ketika sebuah Script disimpan, sistem memeriksa apakah penulis benar-benar memiliki izin resource dan aksi yang dipakai oleh statement-statement di dalamnya. Jika satu saja tidak ada, penyimpanan ditolak (WGL403015). Dengan kata lain, Script yang memuat operasi tanpa izin memang tidak akan pernah tersimpan sejak awal.
    2. Saat pemanggilan (/execute): hanya izin Execute Script milik pemanggil yang diperiksa. Tanpa izin itu, hasilnya 403. Jika lolos, izin resource per statement tidak diperiksa lagi saat runtime; eksekusi langsung berjalan. Cara kerjanya seperti izin eksekusi fungsi dalam pemrograman. Jika Anda memiliki izin untuk menjalankan fungsi tersebut, izin untuk setiap operasi individual di dalamnya tidak ditanyakan lagi.
  • Cakupan kepemilikan: createdBy: ":self" pada filter where berarti "hanya yang dibuat oleh pemanggil saat ini" (misalnya, hanya membaca dompet milik Anda sendiri).
  • Izin yang didelegasikan (perhatian bagi penulis): menggabungkan kedua batas di atas, menjalankan sebuah Script setara dengan bertindak dengan izin penulis yang didelegasikan kepadanya. Pemanggil hanya perlu Execute, dan statement di dalam Script berjalan persis dalam cakupan yang diotorisasikan kepada penulis saat disimpan. Akibatnya, operasi resource yang tidak dapat dilakukan sendiri oleh pemanggil pun tetap bisa terjadi melalui Script. Karena izin yang diberikan kepada penulis itulah jangkauan efektif dari Script tersebut, tentukan dengan cermat operasi apa yang Anda masukkan ke dalam Script.

Daftar periksa ringkas

Sebelum menyimpan, periksa hal-hal berikut.

  • Jika ada panggilan eksternal (Http) atau penyerapan file Media, executionMode bernilai "Async".
  • Anda tidak menempatkan panggilan eksternal di dalam body Loop.
  • Panggilan eksternal 3 atau kurang, SetVar 5 atau kurang, dan total statement 15 atau kurang.
  • Nilai secret hanya dimasukkan melalui secret:true pada Http.headers.
  • Operasi yang tidak dapat dibatalkan (panggilan eksternal) ditempatkan sebisa mungkin di bagian akhir.
  • Jika Anda mengkhawatirkan persaingan update/patch, gunakan version pada ResourceUpdate atau ResourcePatch.
  • Untuk mengembalikan hasil, Anda menentukan Return.value.