پرش به مطلب اصلی

اجرای یک تابع

هدف​

کاری انجام شود بی‌آنکه کسی رکوردی را ذخیره کند: یادآوری‌ای که هر شب فرستاده می‌شود، دسته‌ای از رکوردها که هر ساعت مرتب می‌شوند، یا کاری طولانی که دستی شروع و رها می‌شود تا تمام شود. و بعد بتوان دقیقاً خواند هر اجرا چه کرد.

چرا این وجود دارد​

هر کار دیگری که اسکریپت‌های یک راه‌حل انجام می‌دهند با ذخیرهٔ کسی شروع می‌شود — مرحلهٔ افزونه درون یک نوشتن اجرا می‌شود و API سفارشی وقتی سیستم دیگری آن را صدا بزند. اما برخی کارها دربارهٔ یک نوشتن نیستند: دربارهٔ زمان هستند، یا دربارهٔ دسته‌ای از رکوردها که بزرگ‌تر از آن است که کسی منتظرش بماند.

تابع، اسکریپتی به زبان BS است که سرویس تابع‌ها خودش اجرا می‌کند، در فرایند جداگانهٔ خودش و تا هر وقت که شما اجازه دهید. تابع جزئی از راه‌حل شماست، مثل فرم یا اسکریپت؛ پس در Dev نوشته می‌شود و در بستهٔ راه‌حل به Test و Production می‌رود.

پیش از شروع​

  • یک راه‌حل، با یک ناشر.
  • جدول‌هایی که تابع شما می‌خواند و می‌نویسد.
  • اگر سرویسی بیرونی را صدا می‌زند یا ایمیل می‌فرستد، متغیر محیطی‌ای که آن را نام می‌برد — ببینید فراخوانی یک سرویس بیرونی از اسکریپت.

مراحل​

  1. راه‌حل را باز کنید، در نوار کناری تابع‌ها و سپس جدید را بزنید.
  2. در زبانهٔ اسکریپت بنویسید تابع چه می‌کند. می‌تواند رکورد بخواند و بنویسد، فایل بخواند و بنویسد، سرویس‌های بیرونی را صدا بزند و اسکریپت‌های راه‌حل را import کند — همان کارهایی که مرحلهٔ افزونه می‌تواند. نماد چشم در انتهای نوار زبانه‌ها همهٔ تابع‌هایی را که می‌توانید صدا بزنید فهرست می‌کند.
  3. در زبانهٔ تنظیمات به آن نام نمایشی بدهید. نام منطقی خودش پر می‌شود.
  4. تصمیم بگیرید کی اجرا شود. هر تابعی را می‌توان دستی اجرا کرد. برای اینکه خودش هم اجرا شود، طبق زمان‌بندی اجرا شود را تیک بزنید و فاصله‌ای انتخاب کنید — هر ۱۵ دقیقه، هر ۶ ساعت، هر روز. برای زمان‌بندی روزانه می‌توانید ساعت و منطقهٔ زمانی آن را مشخص کنید.
  5. حداکثر زمان اجرا را تعیین کنید — اینکه یک اجرا چقدر می‌تواند ادامه یابد تا متوقف شود. پیش‌فرض ۱۵ دقیقه است و تا یک روز ممکن است.
  6. ذخیره را بزنید. اسکریپتی که تجزیه نشود همین حالا رد می‌شود، با شمارهٔ خطی که خطا دارد.
  7. اجرا کن را بزنید. زبانهٔ اجراها باز می‌شود و اجرا را دنبال می‌کند: در صف، سپس در حال اجرا، سپس نتیجه. اجرا را انتخاب کنید تا گزارشش را بخوانید.

نوشتن گزارش​

وقتی تابع اجرا می‌شود کسی تماشا نمی‌کند؛ پس گزارش آن راه فهمیدن کاری است که کرد.

var due = queryRecords('par_membership', 'par_reminder_state', 'due');
log('Reminders due: ' + toJson(due.length()));

for (var i: int = 0; i < due.length(); i++) {
updateRecord('par_membership', due[i].id, { par_reminder_state: 'sent' });
log(due[i]);
}
  • متن همان‌طور که هست نوشته می‌شود، عدد همان‌طور که می‌نویسید، و رکورد یا فهرست به‌صورت JSON — پس log(due[i]) کل رکورد را همان‌طور که اجرا دید نشان می‌دهد.
  • زبانهٔ اجراها خطوط را در حین ادامهٔ اجرا نشان می‌دهد، با چند ثانیه تأخیر.
  • هر اجرا حداکثر ۵۰۰۰ خط نگه می‌دارد. آخرین خط نگه‌داشته‌شده می‌گوید گزارش پر است.
  • نگه‌داشتن خطوط گزارش در زبانهٔ تنظیمات گزارش‌گیری را خاموش می‌کند. log همچنان کار می‌کند و چیزی نگه نمی‌دارد؛ پس برای ساکت کردنش — یا روشن کردن دوباره‌اش — هرگز لازم نیست اسکریپت را ویرایش کنید.

پایان دادن عمدی به اجرا​

stop('reason') اجرا را همان‌جا تمام می‌کند، به‌صورت موفقیتی که دلیلش را می‌گوید:

if (due.length() == 0) {
stop('Nobody is due a reminder tonight.');
}

نتیجهٔ اجرا همین جمله را نشان می‌دهد. این با شکست فرق دارد و فهرست اجراها هم آن را همین‌طور نشان می‌دهد.

شروع یک تابع از یک اسکریپت​

یک تابع به ساعت نیازی ندارد. یک Custom API، یک plugin step یا تابعی دیگر می‌تواند با startFunction آن را شروع کند، یک ورودی به آن بدهد و شناسهٔ اجرا را همان لحظه پس بگیرد — کار بعداً در سرویس Functions انجام می‌شود. درخواستی که یک ساعت کار لازم دارد این‌گونه در یک لحظه پاسخ می‌گیرد.

// A Custom API: POST reports { "period": "2026-10" }
var run = startFunction('par_sales_report', { period: getInput('period') });
setStatus(202);
setOutput('run', run);
// The function
var asked = functionInput();
// … the long work …
setResult({ period: asked.period, total: total });
// A second Custom API: GET reports/runs/{run}
var run = functionRun(getInput('run'));
if (run == null) { setStatus(404); } else { setOutput('status', run.status); setOutput('report', run.result); }
  • startFunction(name, input) شناسهٔ اجرا را برمی‌گرداند. ورودی — یک رکورد، یک فهرست، یک مقدار یا null — همان چیزی است که تابع با functionInput() می‌خواند. اجرایی که زمان‌بندی یا Run now شروعش کرده ورودی ندارد و null می‌خواند.
  • setResult(value) چیزی است که اجرا پس می‌دهد. فقط آخرین مقدار نگه داشته می‌شود، و فقط اگر اجرا موفق شود. آن را کوچک نگه دارید — یک خلاصه، یا کلید یک فایل — چون هر بار که کسی وضعیت اجرا را می‌پرسد خوانده می‌شود.
  • functionRun(id) مقدار { id, function, status, outcome, result, queuedAt, startedAt, finishedAt } را برمی‌گرداند، یا null اگر چنین اجرایی نباشد.
  • از یک plugin step، اجرا درون همان نوشتن شروع می‌شود: اگر نوشتن رد شود، اجرا هرگز شروع نمی‌شود.
  • اجراهایی که یک اسکریپت شروع می‌کند به قاعدهٔ «یکی در هر زمان» محدود نیستند. دو نفر که هم‌زمان بخواهند دو اجرا می‌گیرند. قاعدهٔ یکی در هر زمان برای زمان‌بندی و Run now است.
  • در زبانهٔ Runs، چنین اجرایی نحوهٔ شروع: یک اسکریپت را نشان می‌دهد، و با انتخابش ورودی و نتیجه بالای گزارش دیده می‌شوند.
  • اگر تابع وجود نداشته باشد یا خاموش باشد، startFunction اسکریپت را با دلیلش متوقف می‌کند، تا به فراخوان هرگز گفته نشود کاری شروع شده که نشده است.

باخبر شدن از پایان اجرا​

فراخواننده‌ای که نمی‌خواهد مدام بپرسد، می‌تواند باخبر شود. startFunctionWithCallback همان startFunction است با یک آرگومان بیشتر: نام یک متغیر محیطی که نشانی مقصد را نگه می‌دارد. وقتی اجرا تمام شود — به هر شکلی که تمام شود — نتیجهٔ آن یک بار به آن‌جا فرستاده می‌شود.

// A Custom API: POST totals
var run = startFunctionWithCallback('par_invoice_totals', null, 'par_totals_done');
setStatus(202);
setOutput('run', run);

آنچه می‌رسد:

{ "run": "…", "function": "par_invoice_totals", "status": "Succeeded",
"outcome": null, "result": { "invoices": 3, "total": 165.5 }, "finishedAt": "…" }
  • هرگز یک URL در اسکریپت نیست. آرگومان سوم نام یک متغیر محیطی است، همان‌طور که در callService؛ مدیر سیستم برای هر محیط تعیین می‌کند به کجا اشاره کند. نامی که راه‌حل اعلام نکرده باشد، اسکریپت را پیش از شروع هر کاری متوقف می‌کند.
  • یک بار فرستاده می‌شود و تکرار نمی‌شود. در زبانهٔ اجراها، با انتخاب اجرا، اطلاع‌رسانی آن و نتیجه‌اش دیده می‌شود — Delivered (HTTP 200)، وضعیتی که سرویس پاسخ داد، یا دلیل ناتوانی در فراخوانی. فراخواننده‌ای که آن را از دست داده، هنوز می‌تواند اجرا را با functionRun بخواند.
  • وضعیت خود اجرا به آن وابسته نیست. اجرایی که کارش را انجام داده موفق است، حتی اگر سرویسی که باید باخبر می‌شد از کار افتاده باشد.

نوشتن یک فایل​

یک تابع می‌تواند با همان فراخوانی‌هایی که یک Custom API به کار می‌برد — putFile، putFileAs، getFile، listFiles و deleteFile — در فضای ذخیره‌سازی اشیا بنویسد، هرچند هنگام اجرای آن کسی وارد نشده است.

var key = 'orders/' + today() + '.csv';
putFileAs('par-order-exports', key, csv, 'text/csv');
setResult({ bucket: 'par-order-exports', key: key, rows: orders.length() });
  • فایل در فضای ذخیره‌سازی سازمان شما قرار می‌گیرد و از سهمیهٔ ذخیره‌سازی آن کم می‌کند. نوشتنی که از سهمیه فراتر برود، اجرا را ناموفق می‌کند.
  • در مدیریت ← ذخیره‌سازی، بارگذاری‌کنندهٔ فایل function:<name> نوشته می‌شود — تابع آن را نوشته است، نه کسی که اجرا کن را زده است.
  • تابع این‌گونه چیزی بیش از یک خلاصه برمی‌گرداند: داده را در یک فایل بنویسید و کلید فایل را در نتیجه بگذارید.
  • هیچ‌چیز فایل‌های قدیمی را برای شما پاک نمی‌کند. تابعی که هر شب یک فایل می‌نویسد باید فایل‌هایی را که دیگر لازم ندارد پاک کند، همان‌طور که نمونهٔ functions-nightly-export-to-storage می‌کند.

اجرا چگونه تمام می‌شود​

وضعیتچه شد
موفقاسکریپت تمام شد، یا خودش با stop(...) متوقف شد
ناموفقاسکریپت خطا داد، نوشتنی که کرد رد شد، از حداکثر زمان اجرا گذشت، یا سرویس در حین اجرا متوقف شد. نتیجه می‌گوید کدام
لغوشدهکسی لغو اجرا را زد

اجرای ناموفق هرگز خودکار تکرار نمی‌شود. تابع ممکن است مدت زیادی اجرا شود، و تکرار بیست‌ونه دقیقه کار بدون اطلاع شما بدتر از توقف است. بخوانید چرا ناموفق شد، آنچه لازم است را درست کنید و اجرا کن را بزنید.

اطمینان از درستی کار​

  • اجرا موفق است و گزارشش همان چیزی را می‌گوید که انتظار داشتید.
  • رکوردی را که تابع تغییر داده باز کنید و تاریخچهٔ ممیزی آن را ببینید: تغییر به نام تابع ثبت شده، نه یک شخص. تابع به‌عنوان پلتفرم اجرا می‌شود و کسی پشتش نیست.
  • برای تابع زمان‌بندی‌شده، اجرای بعدی در زبانهٔ تنظیمات زمان اجرای خودکار بعدی است.

نکته‌ها​

  • هر بار یک اجرا. تا وقتی اجرایی در صف یا در حال اجراست، «اجرا کن» رد می‌شود و زمان‌بندی‌ای که فرا برسد تا نوبت بعد نادیده گرفته می‌شود. اجرای شبانه‌ای که طول کشیده هرگز دو بار روی همان رکوردها شروع نمی‌شود.
  • «اجرا کن» نسخهٔ ذخیره‌شده را اجرا می‌کند و تا وقتی صفحه تغییر ذخیره‌نشده دارد در دسترس نیست.
  • خاموش یعنی خاموش. تابع خاموش نه طبق زمان‌بندی اجرا می‌شود و نه دستی.
  • تغییر اسکریپت زمان‌بندی را جابه‌جا نمی‌کند؛ تغییر زمان‌بندی می‌کند.
  • لغو اجرا اسکریپت در حال اجرا را ظرف چند ثانیه متوقف می‌کند — حتی حلقه‌ای که به هیچ رکوردی دست نمی‌زند.
  • هر تابع ۲۰۰ اجرای اخیرش را نگه می‌دارد.

عیب‌یابی​

نشانهعلت محتملراه‌حل
اجرا کن غیرفعال استتغییر ذخیره‌نشده، یا تابع خاموش استذخیره کنید؛ روشنش کنید
این تابع در حال اجراستاجرایی در صف یا در حال اجراستصبر کنید، یا آن را انتخاب و لغو اجرا کنید
اجرا ناموفق شد: Stopped after … minutesاز حداکثر زمان اجرا گذشتحداکثر زمان اجرا را بالا ببرید، یا کار هر اجرا را کم کنید
اجرا ناموفق شد: سرویس در حین اجرا متوقف شدسرویس در حین اجرا دوباره راه‌اندازی شددوباره اجرا کنید
گزارش خالی استنگه‌داشتن خطوط گزارش خاموش است، یا اسکریپت هیچ‌جا log را صدا نمی‌زندروشنش کنید؛ log(...) اضافه کنید
اجرا ناموفق شد: There is not enough storage leftسهمیهٔ ذخیره‌سازی سازمان تمام شده استفایل‌هایی را که لازم ندارید پاک کنید، یا طرح را ارتقا دهید
اجرا ناموفق شد: Object storage is not configured for the Functions serviceاستقرار، تنظیمات ذخیره‌سازی را به سرویس توابع نداده استاز مدیر سیستم بپرسید

همچنین ببینید​