> ## Documentation Index
> Fetch the complete documentation index at: https://docs.conare.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# الذكريات المملوكة للمصدر

> أدرج ذكريات مصدر الحقيقة واحذفها عبر (endUserId, source, externalId, version) مع تسليم عديم التأثير، وآمن ضد الأعطال، وآمن ضد اختلاط الترتيب.

استخدم سطح دورة الحياة عندما تعكس الذكريات سجلات تملكها قاعدة بياناتك — صفوف CRM، حقول الملف الشخصي، التذاكر. على عكس `save` التي تُضاف فقط، لهذه الذكريات هوية مُستدامة وتاريخ إصدارات، بحيث تُطبَّق التصحيحات والحذف من مصدر الحقيقة مرة واحدة بالضبط، بالترتيب، مهما كانت الفوضى في التسليم.

## نموذج الهوية

ذاكرة مملوكة للمصدر تُعرَّف بواسطة `(endUserId, source, externalId)`. يجب أن يزداد `version` كلما تغيّر سجل المصدر.

```ts theme={null}
await conare.memories.upsertSource({
  endUserId: "u_123",
  source: "crm-profile",
  externalId: "profile_123",
  version: 7,
  occurredAt: "2026-07-16T10:30:00Z",
  content: "User prefers smaller islands.",
  idempotencyKey: "profile_123:v7",
});
```

## ضمانات التسليم

الطفرات متزامنة، والقواعد بسيطة:

* **إعادة محاولة نفس الإصدار + الحمولة** تُعيد نفس الإيصال المُستدام. إعادة الإرسال بعد عطل آمنة — هذه *هي* قصة التعافي من الأعطال.
* **حمولة مختلفة لإصدار موجود** تُعيد `409`. الإصدارات غير قابلة للتعديل.
* **إصدار أقدم متأخر** يُعيد `409` ولا يكتب أبداً فوق محتوى أحدث أو يُحيي ذاكرة محذوفة.

يتبع الحذف نفس الإصدارات:

```ts theme={null}
await conare.memories.deleteSource({
  endUserId: "u_123",
  source: "crm-profile",
  externalId: "profile_123",
  version: 8,
  occurredAt: "2026-07-17T09:00:00Z",
  idempotencyKey: "profile_123:v8",
});
```

الحذف مُستدام: تتقارب إعادات المحاولة إلى الإيصال الأصلي، ولا يمكن لعمليات upsert المتأخرة بإصدارات أقل إعادة إنشاء الذاكرة.

## التمهيد باستخدام outbox

انعكس السجلات الموجودة بشكل مجمّع عبر `lifecycleBatch` — حتى 100 عنصر و1 ميبايت من المحتوى الإجمالي لكل استدعاء. لا توجد مهمة استيراد من جانب الخادم؛ صندوق outbox من جانب العميل يُعيد الإرسال بعد عطل هو قصة الاستئناف بأكملها:

```ts theme={null}
const result = await conare.memories.lifecycleBatch({
  endUserId: "u_123",
  items: [{
    source: "crm-profile",
    externalId: "profile_123",
    version: 7,
    occurredAt: "2026-07-16T10:30:00Z",
    content: "User prefers smaller islands.",
  }],
});

for (const [index, item] of result.items.entries()) {
  if (item.success || item.code === "stale_source_version") {
    outbox.markDone(index); // that version (or newer) is durable
  } else {
    outbox.scheduleRetry(index, item.code);
  }
}
```

<Note>
  `result.success` يعني فقط "تمت معالجة الدفعة" — تحقق دائماً من النتائج لكل عنصر. علِّم صفاً كمنجز عند `success` **أو** `stale_source_version` (كلاهما يعنيان أن الإصدار دائم بالفعل)، ثم أرسل الدفعة التالية.
</Note>

## القراءة مرة أخرى

`GET /api/v1/memories/{externalId}` يُعيد الذاكرة وأحدث إيصال مُطبَّق — مفيد للتحقق من التقارب بعد الترحيل.
