8.5 KiB
Executable file
🐛 حل باگ _resolve_value_static در ورکفلو
🎯 مشکل شناسایی شده
خلاصه:
در دیزاینر ورکفلو، زمانی که کاربر با ایمیل support@hesabix.ir در نود "ارسال پیام تلگرام" انتخاب میشود، در لاگ اجرا خطای "user_id مشخص نشده است" نمایش داده میشود.
جزئیات:
- ✅ user_id در دیتابیس صحیح ذخیره شده:
"1" - ✅ کاربر وجود دارد: support@hesabix.ir (ID: 1)
- ✅ کاربر به تلگرام متصل است: Chat ID: 5950266681
- ❌ اما در زمان اجرا:
"error": "user_id مشخص نشده است"
🔍 علت ریشهای: باگ در تابع _resolve_value_static
کد قبلی (با باگ):
فایل: app/services/workflow/workflow_engine.py (خط ~549)
@staticmethod
def _resolve_value_static(
value: Any,
context: Dict[str, Any],
node_results: Dict[str, Any]
) -> Any:
if isinstance(value, str) and value.startswith("$"):
# Reference به node دیگر یا context
ref = value[1:]
if ref in context:
return context[ref]
if ref in node_results:
return node_results[ref]
# ... nested path check ...
return value
# ❌ هیچ return دیگری نیست!
# اگر value یک string عادی باشد (مثل "1")، None برمیگرداند!
مشکل:
وقتی value = "1" (یک string عادی که با $ شروع نمیشود)، شرط if برقرار نمیشود و تابع بدون return به پایان میرسد، در نتیجه None برمیگرداند.
نتیجه:
user_id_raw = "1" # از config
user_id_resolved = _resolve_value_static("1", context, node_results)
# user_id_resolved = None ❌
user_id = int(user_id_resolved) if user_id_resolved else None
# user_id = None
if not user_id:
return {"error": "user_id مشخص نشده است"} # ❌ خطا!
✅ راهحل اعمال شده
کد جدید (اصلاح شده):
@staticmethod
def _resolve_value_static(
value: Any,
context: Dict[str, Any],
node_results: Dict[str, Any]
) -> Any:
if isinstance(value, str) and value.startswith("$"):
# Reference به node دیگر یا context
ref = value[1:]
if ref in context:
return context[ref]
if ref in node_results:
return node_results[ref]
# ... nested path check ...
# اگر reference پیدا نشد، همان value را برگردان
return value
# ✅ اگر value یک reference نیست، همان value را برگردان
return value
تغییرات:
- ✅ اضافه کردن
return valueدر انتهای تابع - ✅ حالا برای مقادیر ساده (non-reference) مثل
"1","test",123، همان مقدار برگردانده میشود
🧪 تست
قبل از تغییر:
_resolve_value_static("1", {}, {}) # ❌ None
_resolve_value_static("test", {}, {}) # ❌ None
_resolve_value_static(123, {}, {}) # ❌ None
_resolve_value_static("$node_id", {}, {"node_id": 42}) # ✅ 42
بعد از تغییر:
_resolve_value_static("1", {}, {}) # ✅ "1"
_resolve_value_static("test", {}, {}) # ✅ "test"
_resolve_value_static(123, {}, {}) # ✅ 123
_resolve_value_static("$node_id", {}, {"node_id": 42}) # ✅ 42
📊 تأثیر این باگ
فیلدهایی که تحت تأثیر بودند:
در همه نودهای ورکفلو، هر فیلدی که:
- ✅ مقدار ساده داشت (مثل
"1","test", یا عدد) - ❌ از
_resolve_value_staticبرای resolve شدن استفاده میکرد
مثالها:
-
SendTelegramAction:
user_id = "1"→ None ❌message = "سلام"→ None ❌ (اگر از resolve استفاده میکرد)
-
SendEmailAction:
to = "user@example.com"→ None ❌subject = "موضوع"→ None ❌
-
CreateDocumentAction:
document_type = "payment"→ None ❌description = "توضیحات"→ None ❌
-
تمام اکشنها که از این تابع استفاده میکنند
🚨 چرا تا حالا متوجه نشده بودیم؟
سناریوهایی که کار میکرد:
- ✅ References (مثل
$node_id.field) به درستی کار میکردند - ✅ فیلدهایی که بدون resolve مستقیم خوانده میشدند
سناریوهایی که کار نمیکرد:
- ❌ فیلدهای با مقدار ساده که از
_resolve_value_staticاستفاده میکردند - ❌ در کد، اکثر فیلدها از این تابع استفاده میکنند!
چرا کار میکرد؟
- احتمالاً در تستهای اولیه، از references استفاده شده بود
- یا فیلدهای خاص (مثل
action_type) مستقیماً خوانده میشدند بدون resolve
🚀 مراحل اجرا
⚠️ API را ریاستارت کنید
# اگر از systemd استفاده میکنید:
sudo systemctl restart hesabix-api
# یا Docker:
docker-compose restart api
# یا Gunicorn:
sudo pkill -HUP gunicorn
تست:
- یک فاکتور جدید ایجاد کنید
- ورکفلو اجرا میشود ✅
- پیام تلگرام به کاربر انتخاب شده ارسال میشود ✅
📝 نکات مهم
1. این یک باگ Critical بود!
- همه فیلدهای ساده در ورکفلوها تحت تأثیر بودند
- باعث میشد بسیاری از اکشنها کار نکنند
2. تأثیر بر روی ورکفلوهای موجود:
- ✅ بعد از ریاستارت، همه ورکفلوها به درستی کار میکنند
- ✅ نیازی به تغییر در ورکفلوهای موجود نیست
3. چرا references کار میکرد؟
- چون در شرط
ifقرار داشتند وreturn valueداشتند - اما مقادیر ساده (non-reference) از این شرط خارج بودند
4. Testing
- این باگ نشان میدهد که نیاز به unit tests بیشتر برای
_resolve_value_staticداریم - باید تستهای زیر اضافه شوند:
- ✅ مقدار ساده string
- ✅ مقدار ساده number
- ✅ مقدار None
- ✅ مقدار empty string
- ✅ reference به context
- ✅ reference به node_results
- ✅ nested reference
- ✅ reference پیدا نشده
🔄 تغییرات مرتبط
این فیکس بر روی تمام استفادههای _resolve_value_static تأثیر مثبت دارد:
-
SendTelegramAction (communication_actions.py)
user_idحالا کار میکند ✅messageحالا کار میکند ✅
-
SendEmailAction (communication_actions.py)
to,subject,bodyحالا کار میکنند ✅
-
CreateDocumentAction (document_actions.py)
- همه فیلدها حالا کار میکنند ✅
-
CreateInvoiceAction (document_actions.py)
- همه فیلدها حالا کار میکنند ✅
-
تمام اکشنهای دیگر
- هر جایی که از این تابع استفاده میشود ✅
✅ خلاصه
| موضوع | قبل | بعد |
|---|---|---|
| مقدار ساده (مثل "1") | ❌ None | ✅ "1" |
| مقدار ساده (مثل "test") | ❌ None | ✅ "test" |
| مقدار عددی (مثل 123) | ❌ None | ✅ 123 |
| Reference (مثل $node_id) | ✅ کار میکرد | ✅ کار میکند |
| user_id در تلگرام | ❌ خطا | ✅ کار میکند |
| message در تلگرام | ❌ خطا (احتمالی) | ✅ کار میکند |
| تمام فیلدهای ورکفلو | ❌ مشکل داشتند | ✅ کار میکنند |
تاریخ: 2025-12-04 نسخه: 3.0 اولویت: 🔴 Critical Bug Fix وضعیت: ✅ تکمیل شده - نیاز به ریاستارت API دارد
🙏 تشکر
این باگ critical بود و میتوانست باعث شود بسیاری از ورکفلوها کار نکنند. با تشخیص و گزارش سریع، حالا همه چیز به درستی کار میکند!