عميل التطبيق مفتوح المصدر لـقواعد بيانات الـ schema. شغّله على أي جهاز يمكنه الوصول إلى قاعدة بيانات PostgreSQL الخاصة بك، واقرنه مرة واحدة، فيبقي تلك القاعدة متوافقة مع عمليات الإثراء لديك — بدءًا من اللقطة، ثم تطبيق تدفق فروق حي عبر اتصال WebSocket صادر واحد. ولا تغادر سلسلة الاتصال الخاصة بك ذلك الجهاز أبدًا.
كل عبارة محمية بالمراجعة، لذا تتقارب الدفعة المعاد تسليمها نحو الصفوف نفسها. يؤدي خطأ SQL إلى التراجع عن الدفعة وإيقافها — ولا يتم أبدًا تخطي دلتا مسمومة بصمت.
يسحب العميل الحالة لا العمليات: تحمل كل دلتا الصف (الصفوف) الحالي كاملًا لكيان متغيّر على هيئة INSERT … ON CONFLICT … DO UPDATE عديمة التأثير التكراري، بحيث يتقارب الهدف حتى لو فُقِدت دفعة.
يمكن استهلاك عمليات مزامنة قاعدة البيانات بعدة طرق — n8n أو Make.com أو MCP أو خطافات الويب الخام أو تغذية الدلتا عبر REST. وعميل المزامنة هو المسار المؤتمت بالكامل: الأقل بناءً والأقل تسريبًا.
لا سيناريو n8n، ولا cron، ولا كود ربط. اقترن مرة واحدة، فيبدأ التمهيد من اللقطة، ثم يطبّق كل دلتا فور وصولها.
تُمرَّر سلسلة الاتصال عبر سطر الأوامر أو تُخزَّن محليًا بصلاحيات mode-600 — ولا تُرسَل أبدًا إلى Entity Enricher. يتصل العميل للخارج فقط.
كل دلتا عبارة عن عملية إدراج أو تحديث (upsert) خاملة (idempotent) ومحمية بالمراجعة. إذا توقف العميل في منتصف الدفعة، يُعاد تسليم الدفعة بعد انتهاء صلاحية عقد الإيجار الخاص بها، وتؤدي إعادة التطبيق إلى التقارب نحو الصفوف نفسها.
يؤدي خطأ SQL إلى التراجع عن الدفعة والإبلاغ عن الفارق الفاشل. ويعزل الخادم دفعة ذلك الإثراء بأكملها ويعيد دفع الطابور من دونها، فيبقى العميل متصلًا ويواصل التطبيق — فلا يستطيع صفٌّ معطوب واحد أن يوقف كل ما خلفه، ويظل العمل المعزول مدرجًا حتى تعالجه.
سجّل قاعدة بيانات على schema أولًا، ثم اقرن عميلًا وشغّله على جهاز يمكنه الوصول إلى قاعدة بياناتك.
في صفحة Database Sync، سجّل قاعدة بيانات على المخطط الذي تريد نسخه، ثم راجع مفاتيح قاعدة البيانات الخاصة به. راجع Database Sync للاطلاع على النموذج الكامل. تحدّد هذه الخطوة اللهجة المستهدفة التي سيطبّقها العميل.
الصق هذا في الطرفية. يتحقق البرنامج النصي من توقيع cosign قبل التثبيت.
curl -fsSL https://entityenricher.ai/install-eedatabase.sh | sh
Windows: iwr -useb https://entityenricher.ai/install-eedatabase.ps1 | iex. أو نزّل ملفًا ثنائيًا موقّعًا من الإصدارات، أو ابنِه من المصدر (Go ≥ 1.23): go build -o ee-database .
يتوفّر الكود المصدري والإصدارات الموقّعة على TOT-Concept/ee-database (MIT).
شغّل ee-database pair. تُفتح علامة تبويب في المتصفح على /database/connect برمز قصير — أكّده، واختر أي قاعدة بيانات ينبغي لهذا العميل مزامنتها.
ee-database pair --server https://entityenricher.ai Open this URL in your browser to confirm pairing: https://entityenricher.ai/database/connect?code=7QX-KP2 Code: 7QX-KP2 Waiting for confirmation...
تفضّل استخدام رمز مميّز؟ أصدِر واحدًا من صفحة Database Sync (عميل المزامنة ← إقران عميل) ومرّره مباشرة: ee-database pair --server … <refresh-token>.
في التشغيل الأول، يجلب العميل لقطة .sql ويطبّقها، ثم يتصل ويبثّ عمليات الدلتا. يخزّن --save-dsn سلسلة الاتصال محليًا بحيث لا تحتاج عمليات التشغيل اللاحقة إلى أي وسائط.
يتحقق كل تشغيل ذاتيًا من حقوق التزويد الخاصة بتسجيل الدخول (إنشاء قاعدة البيانات، وDDL، وDML) ويُبلغ عن النتيجة في بطاقة عميل المزامنة، بحيث يظهر أي تصريح مفقود قبل أن تفشل التغييرات في التطبيق. وإذا لم يُنشر بعد أي مخطط مرتبط، يبقى العميل متصلًا وينتظر — إذ يبدأ أول نشر التغذية من تلقاء نفسه، دون الحاجة إلى إعادة التشغيل.
ee-database run --dsn "postgres://user:pass@localhost:5432/mydb" --save-dsn
«بالقرب من» تعني قريبًا على مستوى الشبكة، وليس على خادم قاعدة البيانات: أي جهاز أو حاوية يمكنها الوصول إلى DSN تفي بالغرض — بما في ذلك PostgreSQL المُدارة سحابيًا (Azure وOVHcloud وAWS RDS…)، والتي تفرض عادةً TLS: …/mydb?sslmode=require.
عدة قواعد بيانات على جهاز واحد؟ يرفع مضيف المزامنة عملية الإقران مستوى واحدًا للأعلى: أقرِن الجهاز مرة واحدة، وكل مزامنة قاعدة بيانات تُسنِدها إليه يجري تبنّيها وتهيئتها وإبقاؤها متزامنة تلقائيًا — فتسجيل مزامنة جديدة لا يحتاج أبدًا إلى جلسة طرفية أخرى. ويتطلب ذلك العميل 1.5.0 أو أحدث، إذ يقترن مرة واحدة لكل خادم بدل مرة واحدة لكل جهاز — فيستطيع مضيف واحد خدمة عدة نسخ من Entity Enricher جنبًا إلى جنب.
في صفحة Database Sync، انقر زر Sync hosts في شريط الأدوات وأضف مضيفًا يحمل اسم الجهاز. يظهر رمز اقتران لمرة واحدة مرةً واحدة فقط، مضمَّنًا في أمر host pair جاهز للنسخ واللصق مع خطوات إعداد موجّهة.
شغّل الأمر على الجهاز الذي يمكنه الوصول إلى خادم قاعدة بياناتك. إن --dsn هو سلسلة اتصال أساسية تُسمّي الخادم دون اسم قاعدة بيانات — تشتق كل مزامنة معيّنة قاعدة بياناتها الخاصة منها. وكما هو الحال مع كل DSN، تُخزَّن محليًا بوضع mode-600 ولا تُرسَل أبدًا إلى Entity Enricher.
ee-database host pair --server https://entityenricher.ai \ --dsn "postgres://user:pass@host:5432/" <token>
يتحقق الإقران ذاتيًا من حقوق التزويد الخاصة بتسجيل الدخول (إنشاء قاعدة البيانات، وDDL، وDML) ويفشل مبكرًا عند وجود تصريح مفقود. أتفضّل تسجيل دخول بأقل قدر من الصلاحيات؟ أضف --admin-dsn فيقوم التزويد بإنشاء كل دور وقاعدة بيانات مفقودَين من خلال الاتصال الإداري بدلًا من ذلك — ويُستخدم DSN الإداري وقت التزويد فقط، ولا يُخزَّن أبدًا.
ee-database host run
يحتفظ المضيف باتصال WebSocket واحد لمستوى التحكم ويتفاعل مع التعيينات التي تُجرى في واجهة المستخدم: اختر المضيف عند تسجيل قاعدة بيانات، أو لاحقًا في علامة تبويب النظرة العامة الخاصة بقاعدة البيانات. يتم المطالبة بكل مزامنة معيّنة، وإنشاء قاعدة بياناتها إن كانت مفقودة (بصيغة snake_case مشتقة من اسم المزامنة؛ يمكن تجاوز ذلك لكل مزامنة عبر database_names في config.json الخاص بالمضيف)، ثم مزامنتها عبر الحلقة الاعتيادية أدناه.
يتم الإبلاغ عن أي قاعدة بيانات مقترنة بالفعل بعميل آخر وتخطّيها — ولا يتم الاستيلاء عليها أبدًا. ويؤدي إلغاء المضيف من الواجهة إلى فصل الجهاز فورًا، بما في ذلك كل بيانات اعتماد قاعدة بيانات ادّعاها؛ أما التعيينات والبيانات المتزامنة مسبقًا فتبقى، بحيث يستأنف المضيف المُعاد إقرانه من حيث توقّف القديم.
تغادر الفروق Entity Enricher عبر صندوق صادر صارم من نوع FIFO لكل قاعدة بيانات. يقوم الخادم باستئجار النافذة المرئية لمدة 120 ثانية ويدفعها كدفعة واحدة؛ ويطبّق العميل الدفعة كاملةً في معاملة واحدة ويردّ ack ، ما يقدّم المؤشر ويطلق النافذة التالية فورًا. أما العميل الذي يتعطّل في منتصف الدفعة فيغطّيه انتهاء الإيجار وإعادة دفع من جانب الخادم — فلا يُفقد شيء ولا يُلتزَم به مرتين.
تتشارك التهيئة الأولية والحالة المستقرة مسار كود واحد. تخطَّ التهيئة الأولية عبر --skip-bootstrap إذا كانت قاعدة بياناتك مُهيّأة بالبيانات مسبقًا.
يحمل كل بيان قيمة _sync_revision بحيث لا يستبدل صف أقدم صفًا أحدث أبدًا، حتى لو وصل خارج الترتيب.
يؤدي خطأ SQL إلى التراجع عن الدفعة والإبلاغ عن الفارق الفاشل مع الجملة المخالفة كاملة. ويعزل الخادم دفعة ذلك الإثراء ويعيد دفع الطابور من دونها — بينما يواصل العميل تطبيق البقية. ولا يخرج البرنامج برمز غير صفري إلا عند فشل لا يحدّد أي فارق.
تُبلّغ كل نافذة مُطبَّقة عن البنية التي كتبتها، لكل جدول — بحيث لا يحتاج تقدير حجم إعادة إثراء ليلية إلى التنقيب في السجلات بحثًا عن فروق سبق الإقرار باستلامها واختفت.
applying 12 delta(s) (10831 .. 10842) in one transaction applied 12 delta(s) in 84ms — 38 statement(s): mushroom 4 upserts, mushroom_common_names 12 upserts + 4 prunes, mushroom_human_uses 14 upserts + 4 prunes acked up to delta 10842
كل عملية upsert تعني صفًا واحدًا، لذا فالأعداد هي أعداد صفوف؛ أما prune فهي عملية DELETE واحدة محميّة بالمراجعة تُزيل الصفوف الفرعية أو صفوف الربط التي لم يعد الحمل الجديد يطالب بها. وتُوفَّق الصفوف الفرعية في مكانها — دون مسحها وإعادة إدراجها أبدًا. أضف --verbose للحصول على سطر واحد لكل فرق، يتضمّن نوع الكيان والزمن الفعلي وبنيته الخاصة.
تُحدَّد اللهجة الهدف عبر تسجيل المخطط مع قاعدة البيانات في Entity Enricher — ويطبّق العميل أي SQL يولّده الخادم. PostgreSQL هي لهجة الإطلاق؛ ومن المخطط توفير مولّدات MySQL / MariaDB وSQL Server وOracle (برنامج تشغيل MySQL مضمَّن بالفعل). ويُعالَج تنفيذ التعليمات المتعددة حسب كل برنامج تشغيل (بروتوكول pgx البسيط، وmultiStatements في MySQL).
بافتراض أن قاعدة البيانات الهدف موجودة سلفًا، يحتاج حساب الدخول فقط إلى CONNECT على قاعدة البيانات وUSAGE + CREATE على المخطط الهدف. (منذ PostgreSQL 15، لم يعد public يمنح CREATE للجميع افتراضيًا.)
وكل ما عدا ذلك ينبع من الملكية: فالعميل ينشئ جداول النسخ المطابقة بنفسه، ومن ثم يملكها، والملكية تستلزم عمليات القراءة والكتابة التي تحتاجها فروق البيانات. والملكية ليست أمرًا اختياريًا — إذ يرسل التدفق أيضًا عبارات ترحيل (ALTER TABLE … وCREATE INDEX …) تقصرها PostgreSQL على مالك الجدول، ولا يغني عنها أي مزيج من الصلاحيات.
إذا كانت جداول النسخة المتماثلة موجودة بالفعل تحت مالك مختلف، فسيظل الفحص المسبق لصلاحيات التشغيل ناجحًا — إذ يستطيع حساب الدخول إنشاء جداول جديدة — لكن أول فرق ترحيل سيفشل. انقل ملكيتها عبر ALTER TABLE … OWNER TO <login> (أو امنح حساب الدخول عضوية في الدور المالك) بدلًا من إضافة صلاحيات.
الجملة التي ترفضها قاعدة بياناتك — والسبب المعتاد تكرارٌ سابق تحت فهرس فريد جديد — لا توقف التدفق. تتراجع الدفعة، ويُبلّغ العميل عن الفارق الفاشل مع الجملة المخالفة كاملة (دون أي اقتطاع)، ويعزل الخادم دفعة ذلك الإثراء ويعيد دفع الطابور من دونها. ويواصل عميلك تطبيق كل ما يليها.
تبقى الأعمال المعزولة مدرَجة في تبويب العزل بصفحة Database Sync إلى أن تعالجها: أصلِح السبب في قاعدة بياناتك ثم أعد الحقن — وهو ما يُعيد إسقاط الكيان من حالته الحالية بدل إعادة تنفيذ العبارة القديمة — أو تجاهَلها إن لم يعد للصف أهمية.
ويختلف فشل التهيئة الأولية: فاللقطة معاملة واحدة، فلا يُطبَّق منها شيء جزئيًا، ويحفظها العميل في دليل ملف تعريف الاقتران باسم snapshot-failed.sql (بصلاحية 0600، يُستبدل مع كل محاولة، ويُحذف عند النجاح التالي) لتتمكن من فحصه أو إعادة تشغيله عبر psql -f.
يبدأ العميل اتصال WebSocket عبر :443/wss. ولا يقبل مضيف قاعدة بياناتك أي اتصالات واردة إطلاقًا — لا منافذ لفتحها ولا حركة دخول لتهيئتها.
يرتبط كل اعتماد بمزامنة قاعدة بيانات واحدة. تؤدي إعادة الإقران إلى تدويره وطرد الاتصال المباشر السابق فورًا.
يُستبدَل رمز التحديث ذو 365 يومًا (المخزَّن بصلاحيات mode-600) برموز وصول مدتها 15 دقيقة تُصادق على اتصال WebSocket. ويؤدي الإبطال من الواجهة إلى فصل العميل النشط خلال ثانية واحدة تقريبًا.
يقترن المضيف المُدار بمفتاح قصير يبدأ بـ eeh_… بدلًا من JWT: لا يحتفظ الخادم إلا ببصمته، ولا تنتهي صلاحيته أبدًا، ولا ينتهي إلا بإبطال المضيف من الواجهة.
قفلٌ لكل ملف تعريف يمنع عمليتين من تشغيل الاقتران نفسه في آنٍ واحد — وإلا لأخرجت كلٌّ منهما جلسة WebSocket الأخرى في حلقة لا تنتهي.
شغّل العميل بدور مخصّص محصور في المخطط المتزامن، حتى لا يطال رمز مميّز مخترَق أي شيء آخر — لكن دَع هذا الدور يُنشئ جداول النسخة المطابقة ليملكها. فما تتطلبه عبارات الترحيل هو الملكية لا الأذونات الممنوحة.
| الأمر | ماذا يفعل |
|---|---|
| ee-database pair --server URL | إقران برمز جهاز مؤكَّد عبر المتصفح. اختر قاعدة البيانات المراد مزامنتها. |
| ee-database pair --server URL <token> | الاقتران برمز صادر من صفحة Database Sync (يدعم التشغيل بلا واجهة). |
| ee-database run --dsn DSN [--save-dsn] [--skip-bootstrap] | نفّذ التهيئة الأولية من اللقطة (ما لم تُتخطَّ)، ثم اتصل وطبّق الفروق. |
| ee-database run … --create-missing | أنشئ قاعدة البيانات الهدف أولًا في حال عدم وجودها، باستخدام بيانات اعتماد DSN نفسها (يحتاج postgres إلى صلاحية CREATEDB، وmysql إلى صلاحية CREATE). |
| ee-database run … --create-missing --admin-dsn DSN | تهيئة كل ما يسمّيه DSN الهدف عبر اتصال مسؤول: الدور/المستخدم المفقود (بكلمة مرور DSN) وقاعدة البيانات المملوكة له. عندئذٍ لا يحتاج DSN الهدف إلى أي صلاحيات إنشاء؛ ولا يُخزَّن DSN المسؤول أبدًا. |
| ee-database run --all | مزامنة كل قاعدة بيانات مقترنة بشكل متزامن من عملية واحدة (يحتاج كلٌّ منها إلى DSN محفوظ). |
| ee-database run … --verbose | تسجيل بنية الكتابة والزمن الفعلي لكل فرق، وليس ملخّص كل نافذة فحسب. مقبول أيضًا مع host run. |
| ee-database host pair --server URL --dsn BASE_DSN [--admin-dsn DSN] <token> | اقرن هذا الجهاز مرة واحدة كمضيف مزامنة مُدار — يحدّد DSN الأساسي خادم قاعدة بياناتك (دون اسم قاعدة بيانات) ولا يغادر الجهاز أبدًا؛ ويأتي الرمز من مربّع حوار Sync hosts (زر Sync hosts في شريط الأدوات بصفحة Database Sync). اقتران واحد لكل خادم: يمكنك الاقتران بعدة خوادم Entity Enricher جنبًا إلى جنب. |
| ee-database host run [--server URL] | الوضع المُدار: تتم المطالبة بكل مزامنة قاعدة بيانات مُسنَدة إلى هذا المضيف، وإنشاؤها إن لم تكن موجودة، وإبقاؤها متزامنة تلقائيًا — دون اقتران لكل قاعدة بيانات على حدة، وعبر كل خادم مقترن دفعةً واحدة (--server يحصر ذلك في خادم واحد). أما قاعدة البيانات المقترنة بالفعل بعميل آخر فيُبلَّغ عنها ولا يتم الاستيلاء عليها أبدًا. |
| ee-database host status / host disconnect [--server URL] | اعرض اقترانات المضيف الخاصة بهذا الجهاز أو احذفها. وللإلغاء من جهة الخادم، استخدم بطاقة «مضيفات المزامنة». |
| ee-database status | عرض حالة الإقران وعنوان URL للخادم وقواعد البيانات المقترنة. |
| ee-database disconnect | نسيان بيانات الاعتماد المحلية لأحد الاقترانات. قم بالإلغاء من جانب الخادم عبر واجهة المستخدم. |
| ee-database version | نسخة للطباعة. |
تُخزَّن بيانات الاعتماد بالوضع mode-600، بملف تعريف واحد لكل قاعدة بيانات مقترنة، ضمن ~/.config/ee-database/profiles/ — اقترن مرة واحدة لكل قاعدة بيانات، ويحدد --database NAME واحدة منها عند اقتران عدة قواعد. أتفضّل الاستغناء عن الأتمتة تمامًا؟ التدفق نفسه متاح كـ REST بسيط: GET /api/databases//changes ثم POST /api/databases//ack — راجع Database Sync.
العميل مرخّص بموجب MIT ويوجد في مستودع عام حتى يتمكّن أي شخص من تدقيق ما يُشغَّل تحديدًا مقابل قاعدة بياناته.
المصدر: github.com/TOT-Concept/ee-database
الإصدارات: github.com/TOT-Concept/ee-database/releases — يُوقَّع كل ملف ثنائي باستخدام cosign قبل النشر.
دقّق في المُثبِّت: curl -fsSL https://entityenricher.ai/install-eedatabase.sh | less