برنامهریزی، تحلیل و عملیات پلتفرم · فصل ۴ — Adapter، Capability، Shadow/Direct Publish و Quota · 214
Bounded Direct Publish با Idempotency و Verification
داده و event دارد اما آنها را به مدل تصمیم، attention، experiment یا platform policy قابل توضیح تبدیل نمیکند. موضوع جاری: «Bounded Direct Publish با Idempotency و Verification». میتواند برای «Bounded Direct Publish با Idempotency و Verification» model، signal و guardrail لازم را در یک workflow محدود تعریف و ارزیابی کند.
Bounded Direct Publish with Idempotency and Verification — en-US
خلاصهٔ درس
داده و event دارد اما آنها را به مدل تصمیم، attention، experiment یا platform policy قابل توضیح تبدیل نمیکند. موضوع جاری: «Bounded Direct Publish با Idempotency و Verification».
میتواند برای «Bounded Direct Publish با Idempotency و Verification» model، signal و guardrail لازم را در یک workflow محدود تعریف و ارزیابی کند.
خروجی این درس
میتواند برای «Bounded Direct Publish با Idempotency و Verification» model، signal و guardrail لازم را در یک workflow محدود تعریف و ارزیابی کند.
1. مسئله: Timeout یعنی «نمیدانم»، نه «حتماً Fail شد»
یک POST برای ساخت یا Publish ممکن است به Provider برسد اما پاسخ قبل از رسیدن به Client قطع شود. اگر همان Request را کورکورانه تکرار کنیم، ممکن است محتوای تکراری بسازیم. اگر هم فقط از ترس Duplicate هیچ کاری نکنیم، Transaction میتواند برای همیشه مبهم بماند. خروجی این درس Idempotent Publish Transaction & Verification Ledger v1 است.
2. مرز درس
PLN-023 فقط Transaction مستقیم Publish را از Intent تأییدشده تا Verification نهایی مدل میکند. Shadow promotion مربوط به PLN-022 و Account Health/Quota مربوط به PLN-024 خارج از Scope هستند. Lab کاملاً Synthetic است و هیچ Publish واقعی انجام نمیشود.
3. FACT خارجی و MAKNOW DESIGN
AIP-155 میگوید Request ID مشتری میتواند برای de-duplication، safe retry و idempotency guarantee استفاده شود، اما فقط وقتی API آن را واقعاً honor کند. Google Cloud نیز GET/PUT/DELETE را idempotent و POST/PATCH را ذاتاً non-idempotent میداند. Stateهای Ledger و retry budget این درس MAKNOW DESIGN هستند.
4. Transaction را قبل از Retry هویتدار کن
publish_transaction_id و publish_intent_id باید یک تصمیم Publish مشخص را به target_account و operation وصل کنند. Retry نباید یک Intent جدید یا Account دیگر را ناخواسته اجرا کند.
5. Payload Hash بخشی از Request Identity است
payload_hash فقط برای Debug نیست. اگر همان idempotency key یا request ID با payload دیگری استفاده شود، سیستم نباید آن را «همان Transaction» بداند. Key reuse با payload متفاوت باید DUPLICATE_BLOCKED یا معادل fail-closed بدهد.
6. Provider Support را صریح ثبت کن
idempotency_support مشخص میکند Provider آیا request identity را تضمین میکند یا نه. وجود Header دلخواه در Client به معنی Provider support نیست. اگر Provider مکانیزم رسمی ندارد، باید application-side duplicate strategy را جدا نامگذاری کنیم.
7. Retry Class و Execution Budget را محدود کن
attempt_no، retry_class و execution_budget جلوی retry بینهایت را میگیرند. Timeout با request identity معتبر میتواند Retry-safe باشد؛ Timeout بدون identity و بدون duplicate/read-back evidence باید AMBIGUOUS بماند.
8. Response Status فقط یک Evidence است
200/201/202 میگوید Provider چه Responseای داده، نه اینکه دقیقاً همان Resource موردنظر و فقط یکبار ایجاد شده است. provider_resource_id باید به Intent و Account صحیح bind شود.
9. Read-back Verification را از Response جدا کن
verification_method و read_back_snapshot برای اثبات state نهاییاند. Verification میتواند resource ID، target account، payload fingerprint یا fieldهای بحرانی را دوباره بخواند. اگر read-back در دسترس نیست، VERIFIED را جعل نکن.
10. Duplicate Detection باید قابلردیابی باشد
duplicate_detection میتواند Provider request ID، application duplicate key یا query/read endpoint باشد. اما نوع مکانیزم و محدودیت آن باید در Provenance ثبت شود؛ application key هرگز provider-side exactly-once را اثبات نمیکند.
11. Freshness و Provenance بخشی از Transaction هستند
مستند idempotency، retention window یا verification endpoint ممکن است عوض شود. Evidence قدیمی → STALE_EVIDENCE. Evidence بدون provenance_ref → UNKNOWN یا BLOCKED. برای تصمیم Direct Publish، حدس جای سند را نمیگیرد.
12. Baseline — Timeout با Request ID معتبر
در Baseline، Provider request ID رسمی را پشتیبانی میکند. Attempt اول Timeout میشود؛ Retry با همان request ID و همان payload hash انجام میشود؛ Provider همان Resource را برمیگرداند و read-back Account/Payload را تأیید میکند. نتیجه VERIFIED است.
| case_id | idempotency_support | attempt_no | response_status | verification_method | publish_state | retry_decision | control_reason |
|---|---|---|---|---|---|---|---|
| baseline_provider_request_id | PROVIDER_REQUEST_ID | 2 | 201 | READ_BACK | VERIFIED | NO_RETRY | READ_BACK_MATCHES_INTENT |
| timeout_no_identity | NONE | 1 | TIMEOUT | NONE | AMBIGUOUS | HOLD_AND_INVESTIGATE | TIMEOUT_WITHOUT_SAFE_IDENTITY_OR_DUPLICATE_CHECK |
| key_reused_different_payload | PROVIDER_REQUEST_ID | 2 | 409 | READ_BACK | DUPLICATE_BLOCKED | BLOCKED | REQUEST_ID_REUSED_FOR_DIFFERENT_PAYLOAD |
| success_wrong_target | PROVIDER_REQUEST_ID | 1 | 201 | READ_BACK | FAILED | BLOCKED | READ_BACK_TARGET_MISMATCH |
| budget_exhausted_unverified | PROVIDER_REQUEST_ID | 3 | TIMEOUT | READ_BACK | UNVERIFIED | DEFERRED | EXECUTION_BUDGET_EXHAUSTED |
| stale_idempotency_evidence | PROVIDER_REQUEST_ID | 1 | 201 | READ_BACK | STALE_EVIDENCE | BLOCKED | DECISIVE_EVIDENCE_STALE |
| missing_provenance | PROVIDER_REQUEST_ID | 1 | 201 | READ_BACK | UNKNOWN | BLOCKED | PROVENANCE_MISSING |
| transfer_app_duplicate_read_before_retry | APPLICATION_DUPLICATE_KEY_ONLY | 2 | TIMEOUT_THEN_READ_FOUND | READ_BEFORE_RETRY | VERIFIED | NO_RETRY | READ_BACK_MATCHES_INTENT |
13. Shortcutهای خطرناک
- Timeout را Fail قطعی فرض کنی. ۲)
POSTرا بدون identity دوباره بفرستی. ۳) یک idempotency key را برای payload جدید reuse کنی. ۴) 2xx را exactly-once proof بدانی. ۵) Resource متعلق به Account دیگر را success حساب کنی. ۶) بعد از تمامشدن budget باز هم retry کنی.
14. Transfer — Provider بدون Idempotency Key رسمی
در Transfer، Provider request ID رسمی ندارد اما read endpoint قابلاتکا دارد. Client یک application duplicate key را از Intent+Target+Payload میسازد، قبل از Retry read-before-retry انجام میدهد و فقط اگر Resource موجود مطابق Intent پیدا نشد و budget اجازه داد Request جدید میفرستد. نتیجه میتواند VERIFIED شود، ولی provider_exactly_once=false باقی میماند.
15. Lab، Assessment و Freshness
در lab/PLN-023-LAB1/learner/ دستور python run_checks.py را اجرا کن. هشت Fixture مسیرهای VERIFIED، AMBIGUOUS، DUPLICATE_BLOCKED، FAILED/UNVERIFIED، DEFERRED، STALE_EVIDENCE، UNKNOWN و Transfer را پوشش میدهند. AIP-155 و Google Cloud HTTP guidance در 2026-09-16 دوباره بررسی شدهاند.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
PLN-023-S1 retrieval
Why is approved publish intent different from request identity?
PLN-023-S2 application
Build the ledger for a timed-out create request with a provider request ID.
PLN-023-S3 diagnosis
Why does a 201 response not by itself prove exactly-once publish?
PLN-023-S4 transfer
Design read-before-retry for a provider with no documented idempotency key.
ملاکهای ارزیابی (rubric)
Critical dimensions: lesson boundary; transaction/request identity; payload-key binding; finite retry budget; response versus read-back verification; duplicate detection; freshness/provenance; changed-context transfer.
A passing response must preserve AMBIGUOUS/UNVERIFIED/UNKNOWN/STALE states when evidence is incomplete and must not claim provider-side exactly-once from application-side controls.
منابع و تازگی
مطالعهٔ موارد (case studies)
فایلهای آزمایشگاه
کاملاً آفلاین است؛ API Key و Network لازم نیست.
fixtures/cases.jsonرا بررسی کن.python run_checks.pyرا اجرا کن.- هر بار فقط یک Field تعیینکننده مثل Request Identity، Payload Hash، Target Account، Read-back، Provenance، Freshness یا Retry Budget را تغییر بده.
- علت تغییر State را توضیح بده و هیچ اثر واقعی Provider را ادعا نکن.