در دنیای توسعه بکاند مدرن، ساخت برنامههای توزیعشده و مقاوم پیچیدهتر شده است. معماریهای مونولیتیک جای خود را به میکروسرویسها میدهند و چالشهای جدیدی در مدیریت وضعیت، تحمل خطا و پردازشهای طولانی ایجاد میکنند. در اینجا Temporal وارد میشود؛ یک پلتفرم متنباز که برای حل دقیق همین مشکلات طراحی شده و ساخت برنامههای مقیاسپذیر و بادوام را ساده میکند.
Temporal صرفاً یک کتابخانه نیست؛ بلکه پلتفرمی برای ساخت سیستمهای توزیعشده است که در صورت بروز خطا، بهخوبی مدیریت میشوند. این پلتفرم چارچوبی برای نوشتن کدی فراهم میکند که منطق کسبوکارهای طولانیمدت را به عنوان گردش کار تعریف میکند و تضمین میکند که حتی اگر زیرساخت پایه خراب شود، وضعیت کسبوکار حفظ شده و دقیقاً از جایی که متوقف شده بود، از سر گرفته میشود.
درک مسئله اصلی: ماهیت زودگذر زیرساخت
یک گردش کار معمولی پردازش پرداخت را در نظر بگیرید. این فرآیند ممکن است شامل اعتبارسنجی کارت اعتباری، شارژ حساب کاربر، بهروزرسانی موجودی و ارسال ایمیل تأییدیه باشد. اگر این منطق در یک میکروسرویس استاندارد پیادهسازی شود و سرور پس از شارژ اما پیش از بهروزرسانی موجودی دچار اختلال شود، شما با یک وضعیت ناقص مواجه خواهید شد. اجرای مجدد کل فرآیند ممکن است منجر به شارژ دوگانه حساب کاربر شود.
Temporal این مشکل را با جدا کردن منطق گردش کار از موتور اجرا حل میکند. توسعهدهنده کدی مینویسد که توصیف میکند چه چیزی باید اتفاق بیفتد و موتور Temporal مدیریت میکند که چگونه این اتفاق بیفتد، از جمله پایدارسازی، تلاش مجدد و ترتیب اجرا. این موضوع اغلب به عنوان «ابدیتبخشی» (Eternalization) به وضعیت شناخته میشود.
نحوه عملکرد Temporal: گردش کار، فعالیتها و کلاینتها
برای درک Temporal، باید سه انتزاع اصلی آن را بشناسید:
- گردش کار (Workflows): قطعات منطقی طولانیمدت و بادوام. آنها ارکستراسیون را تعریف میکنند و میتوانند فعالیتها را فراخوانی کنند.
- فعالیتها (Activities): توابع کوتاهمدت و مقاوم در برابر خطا که کار واقعی را انجام میدهند، مانند کوئریهای پایگاه داده یا درخواستهای HTTP.
- کلاینتها (Clients): نقطه ورود برنامه شما برای شروع گردش کارها و ارتباط با سرور Temporal.
مثال عملی: کدنویسی یک گردش کار بادوام
بیایید یک مثال عملی با استفاده از زبان Go بررسی کنیم. فرض کنید گردش کاری داریم که یک سفارش را پردازش میکند. ما میخواهیم اطمینان حاصل کنیم که اگر بررسی موجودی ناموفق باشد، سیستم پیش از رفتن به مرحله بعد، تلاش مجدد انجام دهد. بدون Temporal، مدیریت دستی منطق تلاش مجدد، مهلتهای زمانی و پایدارسازی وضعیت، مستعد خطا است. اما با Temporal، این فرآیند اعلانی (Declarative) است.
package main
import (
"context"
"fmt"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/workflow"
)
// ProcessOrderWorkflow تعریف گردش کار بادوام ماست
func ProcessOrderWorkflow(ctx workflow.Context, orderID string) error {
ao := workflow.ActivityOptions{
StartToCloseTimeout: 10 * time.Second,
}
ctx = workflow.WithActivityOptions(ctx, ao)
// بررسی موجودی - اگر این مرحله شکست بخورد، Temporal بهطور خودکار تلاش مجدد میکند
var inventoryOK bool
err := workflow.ExecuteActivity(ctx, CheckInventory, orderID).Get(ctx, &inventoryOK)
if err != nil {
return fmt.Errorf("failed to check inventory: %w", err)
}
if !inventoryOK {
return fmt.Errorf("item out of stock")
}
// پرداخت را انجام دهید
err = workflow.ExecuteActivity(ctx, ChargePayment, orderID).Get(ctx, nil)
if err != nil {
return fmt.Errorf("payment failed: %w", err)
}
// پایگاه داده را بهروزرسانی کنید
err = workflow.ExecuteActivity(ctx, UpdateOrderStatus, orderID, "SHIPPED").Get(ctx, nil)
return err
}
توجه کنید که کد چگونه شبیه به برنامهنویسی همگام و ترتیبی به نظر میرسد. با این حال، در پشت صحنه، Temporal تاریخچه رویدادها را برای هر مرحله ثبت میکند. اگر فرآیند پس از انجام پرداخت دچار اختلال شود، Temporal گردش کار را از آخرین نقطه بررسی (Checkpoint) بازنویسی میکند، مرحله بررسی موجودی را رد کرده و منطق بهروزرسانی پایگاه داده را بهطور ایمن مجدداً اجرا میکند.
چرا Temporal را انتخاب کنیم؟
پذیرش Temporal توسط توانایی آن در انتزاع پیچیدگی سیستمهای توزیعشده هدایت میشود. این پلتفرم نیاز به ماشینهای وضعیت دستی، منطق تلاش مجدد سفارشی و مکانیزمهای قفلگذاری سطح پایگاه داده برای ارکستراسیون را حذف میکند. با در نظر گرفتن گردش کارها به عنوان شهروندان درجه یک، توسعهدهندگان میتوانند به جای تمرکز بر زیرساختهای فنی، بر منطق کسبوکار تمرکز کنند.
نتیجهگیری
Temporal نشاندهنده یک تغییر پارادایم قابل توجه در نحوه ساخت سیستمهای بکاند است. این پلتفرم به توسعهدهندگان قدرت میدهد تا کدی بنویسند که ذاتاً مقاوم، مقیاسپذیر و قابل نگهداری باشد. با پذیرش ارکستراسیون گردش کار بادوام، تیمها میتوانند سربار عملیاتی را کاهش داده و اطمینان حاصل کنند که برنامههای آنها حتی در مواجهه با شکستهای اجتنابناپذیر نیز سازگاری خود را حفظ میکنند. برای توسعهدهندگان متوسط تا پیشرفتهای که به دنبال ارتقای قابلیت اطمینان سیستمهای خود هستند، Temporal ابزاری ضروری در جعبه ابزار معماری مدرن محسوب میشود.