يمكن أن تفشل الطلبات التي تقوم بها إلى تخزين البيانات بسبب ضعف الاتصال أو مشاكل أخرى. للتعامل مع الأخطاء وإرجاع رسائل مع رمز خطأ، قم بلف وظائف تخزين البيانات في pcall().
تعني مكالمة الكتابة الفاشلة، مثل UpdateAsync(), أن خادم اللعبة لم يتلق استجابة ناجحة. لا يضمن ذلك دائمًا أن الكتابة في الخلفية لم تحدث. في بعض سيناريوهات الفشل، قد تكون حالة الكتابة النهائية غير معروفة للمتصل حتى يتم التحقق منها بقراءة متابعة بدون ذاكرة تخزين مؤقت.
مرجع رموز الأخطاء
| رمز الخطأ | اسم الخطأ | رسالة الخطأ | ملاحظات | |
|---|---|---|---|---|
| 101 | KeyNameEmpty | لا يمكن أن يكون اسم المفتاح فارغًا. | تحقق مما إذا كان الإدخال الخاص بالمفتاح في وظيفة تخزين البيانات هو سلسلة فارغة. | |
| 102 | KeyNameLimit | يتجاوز اسم المفتاح حد 50 حرفًا. | تحقق مما إذا كان الإدخال الخاص بالمفتاح في وظيفة تخزين البيانات يتجاوز طول 50. | |
| 103 | ValueNotAllowed | لا يمكن السماح بـ X في DataStore. | أرجعت وظيفة التحديث السيئة قيمة من النوع X. | |
| 104 | CantStoreValue | لا يمكن تخزين X في DataStore. | أرجعت وظيفة التحديث قيمة من النوع X لم يتم تسلسلها. | |
| 105 | ValueTooLarge | تتجاوز القيمة المسلسلة حد X. | إذا كنت تقوم بتعيين قيمة باستخدام SetAsync() أو UpdateAsync(), لا يمكن أن يتجاوز الطول المسلسل للقيمة الحجم X. للتحقق من الطول المسلسل للبيانات، استخدم JSONEncode(). | |
| 106 | MaxValueInvalid | يجب أن يكون MaxValue عددًا صحيحًا. | إذا كنت تمرر قيمة قصوى إلى GetSortedAsync() لـ OrderedDataStore, يجب أن تكون عددًا صحيحًا. | |
| 106 | MinValueInvalid | يجب أن يكون MinValue عددًا صحيحًا. | إذا كنت تمرر قيمة دنيا إلى GetSortedAsync() لـ OrderedDataStore, يجب أن تكون عددًا صحيحًا. | |
| 106 | PageSizeGreater | يجب أن يكون PageSize ضمن نطاق محدد مسبقًا. | أقل حجم صفحة لـ OrderedDataStore هو 1. | |
| 106 | PageSizeLesser | يجب أن يكون PageSize ضمن نطاق محدد مسبقًا. | أقصى حجم صفحة لـ OrderedDataStore هو 100. | |
| 107 | MinMaxOrderInvalid | يجب أن يكون MaxValue أكبر من أو يساوي MinValue. | يجب أن تكون القيمة القصوى أكبر من أو تساوي القيمة الدنيا لـ GetSortedAsync(). | |
| 301 | GetAsyncThrottle | تم إسقاط طلب GetAsync. تم تقييد الطلب ولكن كانت قائمة الانتظار ممتلئة. | تجاوز طلب GetAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | |
| 302 | SetAsyncThrottle | تم إسقاط طلب SetAsync. تم تقييد الطلب ولكن كانت قائمة الانتظار ممتلئة. | تجاوز طلب SetAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | |
| 303 | IncreAsyncThrottle | تم إسقاط طلب IncrementAsync. تم تقييد الطلب ولكن كانت قائمة الانتظار ممتلئة. | تجاوز طلب IncrementAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | |
| 304 | UpdateAsyncThrottle | تم إسقاط طلب UpdateAsync. تم تقييد الطلب ولكن كانت قائمة الانتظار ممتلئة. | تجاوز طلب UpdateAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | |
| 304 | TransformThrottle | تم إسقاط طلب UpdateAsync. تم تقييد الطلب ولكن كانت قائمة الانتظار ممتلئة. | تجاوز طلب UpdateAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | |
| 305 | GetSortedThrottle | تم إسقاط طلب GetSorted. تم تقييد الطلب ولكن كانت قائمة الانتظار ممتلئة. | تجاوز طلب GetSortedAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | |
| 306 | RemoveAsyncThrottle | تم إسقاط طلب RemoveAsync. تم تقييد الطلب ولكن كانت قائمة الانتظار ممتلئة. | تجاوز طلب RemoveAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | |
| 401 | DataModelNoAccess | فشل الطلب. DataModel غير متاح أثناء إيقاف التجربة. | DataModel غير مُهيأ لأن التجربة تتوقف. | |
| 402 | LuaWebSrvsNoAccess | فشل الطلب. LuaWebService غير متاح أثناء إيقاف التجربة. | LuaWebService غير مُهيأ لأن التجربة تتوقف. | |
| 403 | StudioAccessToApisNotAllowed | لا يمكن الكتابة إلى DataStore من الاستوديو لأن الوصول إلى واجهة برمجة التطبيقات غير مفعل. | يجب أن يكون الوصول إلى واجهة برمجة التطبيقات نشطًا لاستخدام تخزين البيانات في الاستوديو. | |
| 404 | InternalError | لا يوجد OrderedDataStore. | لم يتم العثور على OrderedDataStore المرتبط بهذا الطلب. قد يكون هذا علامة على تلف البيانات. حاول مرة أخرى لاحقًا. | |
| 501 | InternalError | لا يمكن تحليل الاستجابة لأن البيانات قد تكون تالفة. | لم يتمكن الخادم من تحليل الاستجابة لطلبك. قد يكون هذا علامة على تلف البيانات. حاول مرة أخرى لاحقًا. | |
| 502 | RequestRejected | رفضت خدمات واجهة برمجة التطبيقات الطلب مع الخطأ X. | حدث خطأ X أثناء المعالجة على خوادم Roblox. حاول مرة أخرى لاحقًا. | |
| 503 | InternalError | كان طلب تخزين البيانات ناجحًا ولكن لم يتم العثور على المفتاح. | لم يتم العثور على المفتاح المطلوب في تخزين البيانات. قد يكون هذا علامة على تلف البيانات. حاول مرة أخرى لاحقًا. | |
| 504 | InternalError | كان طلب تخزين البيانات ناجحًا ولكن لم يتم تنسيق الاستجابة بشكل صحيح. | لم يتمكن الخادم من تحليل الاستجابة لطلبك. قد يكون هذا علامة على تلف البيانات. حاول مرة أخرى لاحقًا. | |
| 505 | InternalError | كان طلب OrderedDataStore ناجحًا ولكن لم يتم تنسيق الاستجابة بشكل صحيح. | لم يتمكن الخادم من تحليل الاستجابة لطلب OrderedDataStore. قد يكون هذا علامة على تلف البيانات. حاول مرة أخرى لاحقًا. | |
| 509 | OperationNotAllowed | تم حظر عمليات تخزين البيانات أثناء التشغيل على RCC شخصي لمنع تلف البيانات المحتمل. | تم حظر كتابات تخزين البيانات على قنوات RCC الخاصة. | |
| 511 | AttributeSizeTooLarge | يتجاوز حجم سمة البيانات الوصفية حد X. | يتجاوز حجم البيانات الوصفية المسلسل الحد X. القيمة X ديناميكية. إذا تغير الحجم، تتغير القيمة أيضًا. | |
| 512 | UserIdLimitExceeded | يتجاوز حجم UserID حد X. | يتجاوز طول مصفوفة معرفات المستخدم المقدمة من المستخدم الحد X. | |
| 513 | AttributeFormatError | تنسيق السمة userId غير صالح. | معرف المستخدم المقدم ليس رقمًا. | |
| 513 | AttributeFormatError | تنسيق بيانات التعريف غير صالح. | البيانات الوصفية ليست جدولاً. | |
| GetVersionAsyncThrottle | تم إسقاط طلب GetVersionAsync. تم تقييد الطلب. | تجاوز طلب GetVersionAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | ||
| GetVersionAtTimeAsyncThrottle | تم إسقاط طلب GetVersionAtTimeAsync. تم تقييد الطلب. | تجاوز طلب GetVersionAtTimeAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | ||
| ListDataStoresAsyncThrottle | تم إسقاط طلب ListDataStoresAsync. تم تقييد الطلب. | تجاوز طلب ListDataStoresAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | ||
| ListKeysAsyncThrottle | تم إسقاط طلب ListKeysAsync. تم تقييد الطلب. | تجاوز طلب ListKeysAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | ||
| ListVersionsAsyncThrottle | تم إسقاط طلب ListVersionsAsync. تم تقييد الطلب. | تجاوز طلب ListVersionsAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | ||
| RemoveVersionAsyncThrottle | تم إسقاط طلب RemoveVersionAsync. تم تقييد الطلب. | تجاوز طلب RemoveVersionAsync() الحد الأقصى لحجم قائمة الانتظار ولا يمكن لـ Roblox معالجة الطلبات عند معدل النقل الحالي. | ||
| InvalidTimestamp | يجب أن تكون الطابع الزمني إيجابيًا وألا يزيد عن عشر دقائق في المستقبل. | لم يكن الطابع الزمني المقدم إلى GetVersionAtTimeAsync() صالحًا. | ||
| StandardReadExperienceThrottled | تم تقييد طلب StandardRead بواسطة حدود التجربة. | تجاوز طلب إلى GetAsync(), GetVersionAsync(), GetVersionAtTimeAsync(), أو قراءة UpdateAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل تجربة StandardRead. | ||
| StandardWriteExperienceThrottled | تم تقييد طلب StandardWrite بواسطة حدود التجربة. | تجاوز طلب إلى SetAsync(), IncrementAsync(), أو كتابة UpdateAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل تجربة StandardWrite. | ||
| StandardListExperienceThrottled | تم تقييد طلب StandardList بواسطة حدود التجربة. | تجاوز طلب إلى ListKeysAsync(), ListVersionsAsync(), أو ListDataStoresAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل تجربة StandardList. | ||
| StandardRemoveExperienceThrottled | تم تقييد طلب StandardRemove بواسطة حدود التجربة. | تجاوز طلب إلى RemoveAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل تجربة StandardRemove. | ||
| OrderedReadExperienceThrottled | تم تقييد طلب OrderedRead بواسطة حدود التجربة. | تجاوز طلب إلى GetAsync(), BatchGetAsync(), أو قراءة UpdateAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل تجربة OrderedRead. | ||
| OrderedWriteExperienceThrottled | تم تقييد طلب OrderedWrite بواسطة حدود التجربة. | تجاوز طلب إلى SetAsync(), IncrementAsync(), أو كتابة UpdateAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل تجربة OrderedWrite. | ||
| OrderedListExperienceThrottled | تم تقييد طلب OrderedList بواسطة حدود التجربة. | تجاوز طلب إلى GetSortedAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل تجربة OrderedList. | ||
| OrderedRemoveExperienceThrottled | تم تقييد طلب OrderedRemove بواسطة حدود التجربة. | تجاوز طلب إلى RemoveAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل تجربة OrderedRemove. | ||
| StandardReadGameServerThrottled | تم تقييد طلب StandardRead بواسطة حدود خادم اللعبة أو كانت قائمة الانتظار ممتلئة. | تجاوز طلب إلى GetAsync(), GetVersionAsync(), GetVersionAtTimeAsync(), أو قراءة UpdateAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل خادم اللعبة StandardRead. | ||
| StandardWriteGameServerThrottled | تم تقييد طلب StandardWrite بواسطة حدود خادم اللعبة أو كانت قائمة الانتظار ممتلئة. | تجاوز طلب إلى SetAsync(), IncrementAsync(), أو كتابة UpdateAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل خادم اللعبة StandardWrite. | ||
| StandardListGameServerThrottled | تم تقييد طلب StandardList بواسطة حدود خادم اللعبة أو كانت قائمة الانتظار ممتلئة. | تجاوز طلب إلى ListKeysAsync(), ListVersionsAsync(), أو ListDataStoresAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل خادم اللعبة StandardList. | ||
| StandardRemoveGameServerThrottled | تم تقييد طلب StandardRemove بواسطة حدود خادم اللعبة أو كانت قائمة الانتظار ممتلئة. | تجاوز طلب إلى RemoveAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل خادم اللعبة StandardRemove. | ||
| OrderedReadGameServerThrottled | تم تقييد طلب OrderedRead بواسطة حدود خادم اللعبة أو كانت قائمة الانتظار ممتلئة. | تجاوز طلب إلى GetAsync(), BatchGetAsync(), أو قراءة UpdateAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل خادم اللعبة OrderedRead. | ||
| OrderedWriteGameServerThrottled | تم تقييد طلب OrderedWrite بواسطة حدود خادم اللعبة أو كانت قائمة الانتظار ممتلئة. | تجاوز طلب إلى SetAsync(), IncrementAsync(), أو كتابة UpdateAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل خادم اللعبة OrderedWrite. | ||
| OrderedListGameServerThrottled | تم تقييد طلب OrderedList بواسطة حدود خادم اللعبة أو كانت قائمة الانتظار ممتلئة. | تجاوز طلب إلى GetSortedAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل خادم اللعبة OrderedList. | ||
| OrderedRemoveGameServerThrottled | تم تقييد طلب OrderedRemove بواسطة حدود خادم اللعبة أو كانت قائمة الانتظار ممتلئة. | تجاوز طلب إلى RemoveAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل خادم اللعبة OrderedRemove. |
رموز أخطاء الخادم
| اسم الخطأ | رسالة الخطأ | ملاحظات |
|---|---|---|
| DatastoreDeleted | تم حذف تخزين البيانات. | لم يكن بالإمكان إجراء عملية على تخزين البيانات لأن تخزين البيانات تم حذفه سابقًا. |
| DatastoreThrottled | يتجاوز معدل الطلبات الحد الأقصى المسموح به لـ datastore. | تم إرسال الكثير من الطلبات إلى تخزين بيانات واحد. |
| InternalServerError | حدث خطأ داخلي في الخادم. | خطأ عرضي على خوادم Roblox. حاول مرة أخرى، ويفضل مع تراجع أسي. |
| InvalidExclusiveStartKey | مفتاح البداية الحصري المقدم غير صالح. | المفتاح الحصري (المؤشر) المقدم لعملية قائمة مثل ListKeysAsync() غير صالح. |
| InvalidPlace | المكان المقدم غير صالح. | لا يوجد معرف كون عالمي مطابق للمكان. حاول مرة أخرى لاحقًا. |
| InvalidTarget | الهدف المقدم غير صالح. | يتجاوز اسم مفتاح تخزين البيانات المرتب حد 50 حرفًا. |
| InvalidUniverse | الكون المقدم غير صالح. | لا يوجد معرف مكان مطابق للكون. حاول مرة أخرى لاحقًا. |
| InvalidUserIds | معرفات المستخدم المقدمة لها تنسيق غير صالح. | فشل في تحليل معرفات المستخدم. |
| KeyThrottled | يتجاوز معدل الطلبات الحد الأقصى المسموح به للمفتاح. | يتجاوز معدل الطلبات الحد الأقصى المسموح به لمفتاح واحد. |
| KeyNotFound | المفتاح المطلوب غير موجود. | المفتاح غير موجود. |
| N/A | لا توجد صفحات للتقدم إليها. | يحدث هذا الخطأ عندما تستدعي Pages:AdvanceToNextPageAsync() على الصفحة الأخيرة. |
| StandardReadExperienceThrottled | يتجاوز معدل طلب القراءة القياسي الحد الأقصى المسموح به للتجربة. | تجاوز طلب إلى GetAsync(), GetVersionAsync(), GetVersionAtTimeAsync(), أو قراءة UpdateAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل تجربة StandardRead. |
| StandardWriteExperienceThrottled | يتجاوز معدل طلب الكتابة القياسي الحد الأقصى المسموح به للتجربة. | تجاوز طلب إلى SetAsync(), IncrementAsync(), أو كتابة UpdateAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل تجربة StandardWrite. |
| StandardListExperienceThrottled | يتجاوز معدل طلب القائمة القياسي الحد الأقصى المسموح به للتجربة. | تجاوز طلب إلى ListKeysAsync(), ListVersionsAsync(), أو ListDataStoresAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل تجربة StandardList. |
| StandardRemoveExperienceThrottled | يتجاوز معدل طلب الإزالة القياسي الحد الأقصى المسموح به للتجربة. | تجاوز طلب إلى RemoveAsync() على تخزين بيانات قياسي الحد الأقصى لمعدل تجربة StandardRemove. |
| OrderedReadExperienceThrottled | يتجاوز معدل طلب القراءة المرتب الحد الأقصى المسموح به للتجربة. | تجاوز طلب إلى GetAsync(), BatchGetAsync(), أو قراءة UpdateAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل تجربة OrderedRead. |
| OrderedWriteExperienceThrottled | يتجاوز معدل طلب الكتابة المرتب الحد الأقصى المسموح به للتجربة. | تجاوز طلب إلى SetAsync(), IncrementAsync(), أو كتابة UpdateAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل تجربة OrderedWrite. |
| OrderedListExperienceThrottled | يتجاوز معدل طلب القائمة المرتب الحد الأقصى المسموح به للتجربة. | تجاوز طلب إلى GetSortedAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل تجربة OrderedList. |
| OrderedRemoveExperienceThrottled | يتجاوز معدل طلب الإزالة المرتب الحد الأقصى المسموح به للتجربة. | تجاوز طلب إلى RemoveAsync() على تخزين بيانات مرتب الحد الأقصى لمعدل تجربة OrderedRemove. |
الحدود
تحتوي نماذج البيانات على حدود. إذا تجاوزت تجربة هذه الحدود، فإن الخدمة تقوم تلقائيًا بتقييد استخدام تخزين البيانات للتجربة وتسبب في وضع الطلبات المستقبلية في واحدة من قوائم الانتظار التالية:
- تعيين
- تعيين مرتب
- الحصول
- الحصول المرتب
يتم التعامل مع الطلبات في قائمة الانتظار بالترتيب الذي تم استلامها. تستمر الوظيفة المستدعاة في الانتظار طالما أن طلبها لا يزال في قائمة الانتظار. إذا تم تقييد مفتاح تخزين البيانات نفسه، يتم وضع الطلب في قائمة الانتظار ولكن يتم تخطيه مؤقتًا.
كل قائمة لديها حد 30 طلبًا. عندما يتم الوصول إلى حد قائمة، تفشل الطلبات مع رمز خطأ في نطاق 301-306، مما يشير إلى أن الطلبات قد تم إسقاطها تمامًا.
حدود الوصول
تخضع تخزين البيانات لكل من حدود التجربة وحدود الخادم. تتوسع حدود مستوى التجربة مع إجمالي المستخدمين المتزامنين عبر التجربة، بينما تكون حدود مستوى الخادم قابلة للتكوين ومخصصة للاستخدام كأداة من قبل المنشئ.
حدود التجربة
يسمح لكل تجربة بعدد معين من طلبات تخزين البيانات بناءً على نوع تخزين البيانات، نوع الطلب، وعدد المستخدمين المتزامنين. لكل نوع من أنواع تخزين البيانات ونوع الطلب، يتم مشاركة الحد بين جميع الوظائف المدرجة.
- يستهلك UpdateAsync() من كل من ميزانيات طلبات القراءة والكتابة. ستقوم مكالمة واحدة بتقليل كلا الحدين.
- يشارك خادم اللعبة وOpen Cloud ميزانية؛ يمكن أن يتم تقييد حركة مرور Open Cloud بواسطة الاستخدام داخل التجربة (وعكس ذلك). انظر التحكم في حدود المعدل للحصول على مزيد من الإرشادات.
تخزين البيانات القياسي
| نوع الطلب | واجهة برمجة التطبيقات لخادم اللعبة | واجهة برمجة التطبيقات لـ Open Cloud | الحدود المشتركة (الطلبات في الدقيقة) |
|---|---|---|---|
| قراءة | GetAsync() GetVersionAsync() GetVersionAtTimeAsync() UpdateAsync() | الحصول على إدخال تخزين البيانات | 300 + concurrentUsers × 40 |
| كتابة | SetAsync() IncrementAsync() UpdateAsync() | إنشاء، تحديث، زيادة إدخال تخزين البيانات | 300 + concurrentUsers × 20 |
| قائمة | ListDataStoresAsync() ListKeysAsync() ListVersionsAsync() | قائمة تخزين البيانات، قائمة إدخالات تخزين البيانات، قائمة مراجعات إدخالات تخزين البيانات | 300 + concurrentUsers × 2 |
| إزالة | RemoveAsync() | حذف إدخال تخزين البيانات، حذف تخزين البيانات، استعادة تخزين البيانات المحذوف | 300 + concurrentUsers × 40 |
تخزين البيانات المرتب
| نوع الطلب | واجهة برمجة التطبيقات لخادم اللعبة | واجهة برمجة التطبيقات لـ Open Cloud | الحدود المشتركة (الطلبات في الدقيقة) |
|---|---|---|---|
| قراءة | GetAsync() BatchGetAsync() UpdateAsync() | الحصول على إدخال تخزين البيانات المرتب | 300 + concurrentUsers × 40 |
| كتابة | SetAsync() IncrementAsync() UpdateAsync() | إنشاء، تحديث، زيادة إدخال تخزين البيانات المرتب | 300 + concurrentUsers × 20 |
| قائمة | GetSortedAsync() | قائمة إدخالات تخزين البيانات المرتب | 300 + concurrentUsers × 2 |
| إزالة | RemoveAsync() | حذف إدخال تخزين البيانات المرتب | 300 + concurrentUsers × 40 |
التحكم في حدود المعدل
نظرًا لأن طلبات Open Cloud وخادم اللعبة مشتركة، من المهم التحكم بشكل مستقل في مقدار ما يمكن لكل منهما استهلاكه من الميزانية.
خادم اللعبة
تمتلك الخوادم الفردية حدودًا مدمجة، كما هو موضح أعلاه. استخدم مجموعة من SetRateLimitForRequestType() و GetRequestBudgetForRequestType() للحفاظ على التحكم الدقيق في مساهمة الخوادم الفردية في الميزانية الإجمالية.
Open Cloud
تتطلب طلبات Open Cloud حلاً خارجيًا لتحديد معدل الطلبات. نوصي بإحدى الطرق التالية:
- (بسيطة) أضف مهلة قصيرة بعد كل طلب، خاصة إذا كنت تستدعي نفس واجهة برمجة التطبيقات في حلقة مستمرة. قم بتعيين هذه المهلة لتكون مساوية لـ 60 / (الاستهلاك المطلوب للميزانية في الدقيقة) ثوانٍ، كحد أعلى. لاحظ أن هذه الطريقة لا تسمح بإرسال الطلبات في دفعات.
- (قوية) تنفيذ محدد معدل محلي باستخدام استراتيجية دلو التسرب.
تتضمن عينات كود Node.js التالية تنفيذات مرجعية.
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('The API_KEY environment variable is not set.');
}
const apiHeaderKey = 'x-api-key';
const universeId = '';
const dataStoreId = 'Inventory';
const baseUrl = 'https://apis.roblox.com/cloud/v2/';
// --- إعداد تحديد معدل لكل عملية (طلبات في الدقيقة) ---
const LIST_RATE_PER_MIN = 60;
const GET_RATE_PER_MIN = 120;
const UPDATE_RATE_PER_MIN = 60;
// الحد الأقصى للفاصل الزمني لكل عملية: 60 / (الطلبات في الدقيقة) ثوانٍ.
const LIST_INTERVAL_MS = (60 / LIST_RATE_PER_MIN) * 1000;
const GET_INTERVAL_MS = (60 / GET_RATE_PER_MIN) * 1000;
const UPDATE_INTERVAL_MS = (60 / UPDATE_RATE_PER_MIN) * 1000;
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// ينفذ الطلب، ثم ينتظر الفاصل الزمني الخاص بهذه العملية قبل العودة.
async function throttledFetch(url, options, intervalMs) {
const response = await fetch(url, options);
await sleep(intervalMs);
return response;
}
async function listEntries(universe, dataStore) {
const listPath = `universes/${universe}/data-stores/${dataStore}/entries`;
const url = baseUrl + listPath;
const response = await throttledFetch(url, {
headers: { [apiHeaderKey]: apiKey }
}, LIST_INTERVAL_MS);
return response.json();
}
async function getEntry(path) {
const url = baseUrl + path;
const response = await throttledFetch(url, {
headers: { [apiHeaderKey]: apiKey }
}, GET_INTERVAL_MS);
return response.json();
}
async function updateEntry(path, payload) {
const url = baseUrl + path;
const response = await throttledFetch(url, {
method: 'PATCH',
headers: {
[apiHeaderKey]: apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload) // يجب أن تكون الجسم سلسلة
}, UPDATE_INTERVAL_MS);
return response;
}
(async () => {
try {
const entries = await listEntries(universeId, dataStoreId);
for (const entry of entries.dataStoreEntries) {
const path = entry.path;
console.log(`\nProcessing entry: ${path}`);
const currentData = await getEntry(path);
currentData.value.currency += 10;
const payload = { value: currentData.value };
const updateResponse = await updateEntry(path, payload);
console.log(`Status: ${updateResponse.status}`);
console.log(`Response: ${await updateResponse.text()}`);
}
} catch (error) {
console.error('An error occurred during execution:', error);
}
})();حدود الخادم
تمتلك كل خادم حد معدل قابل للتكوين لكل نوع طلب، بناءً على عدد اللاعبين في ذلك الخادم. تتلقى الخوادم دفعة بدء واحدة من ميزانية الطلبات الإضافية عندما يتم إنشاؤها لأول مرة. استخدم GetRequestBudgetForRequestType() لتأكيد عدد طلبات تخزين البيانات التي يمكن أن يقوم بها الخادم الحالي في أي وقت.
تكون هذه الحدود قابلة للتكوين من قبل المنشئ باستخدام SetRateLimitForRequestType() واجهة برمجة التطبيقات. باستخدام هذه الواجهة، يمكن للمنشئ تكوين حدود معدل تخزين البيانات الخاصة بهم لكل نوع طلب.
تطبق الحدود الافتراضية التالية إذا لم يتم استدعاء واجهة برمجة التطبيقات:
تخزين البيانات القياسي
| نوع الطلب | DataStoreRequestType Enum | واجهة برمجة التطبيقات لخادم اللعبة | طلبات في الدقيقة |
|---|---|---|---|
| قراءة | StandardRead | GetAsync() GetVersionAsync() GetVersionAtTimeAsync() UpdateAsync() | 60 + numPlayers × 40 |
| كتابة | StandardWrite | SetAsync() IncrementAsync() UpdateAsync() | 60 + numPlayers × 40 |
| قائمة | StandardList | ListDataStoresAsync() ListKeysAsync() ListVersionsAsync() | 5 + numPlayers × 2 |
| إزالة | StandardRemove | RemoveAsync() | 60 + numPlayers × 40 |
| إزالة الإصدار (مهمل) | RemoveVersionAsync | RemoveVersionAsync() | 5 + numPlayers × 2 |
تخزين البيانات المرتب
| نوع الطلب | DataStoreRequestType Enum | واجهة برمجة التطبيقات لخادم اللعبة | طلبات في الدقيقة |
|---|---|---|---|
| قراءة | OrderedRead | GetAsync() BatchGetAsync() UpdateAsync() | 60 + numPlayers × 40 |
| كتابة | OrderedWrite | SetAsync() IncrementAsync() UpdateAsync() | 30 + numPlayers × 5 |
| قائمة | OrderedList | GetSortedAsync() | 5 + numPlayers × 2 |
| إزالة | OrderedRemove | RemoveAsync() | 30 + numPlayers × 5 |
حدود البيانات
تحدد تخزين البيانات مقدار البيانات التي يمكن استخدامها لكل إدخال.
يجب أن يكون اسم تخزين البيانات، اسم المفتاح، والنطاق جميعها تحت طول حرف معين. استخدم string.len() للتحقق من طولها.
تُخزن البيانات (قيمة المفتاح) أيضًا كسلسلة، بغض النظر عن نوعها الأولي. يمكنك التحقق من حجم البيانات باستخدام وظيفة JSONEncode()، التي تحول بيانات Luau إلى جدول JSON مسلسلة.
| المكون | الحد الأقصى لعدد الأحرف |
|---|---|
| اسم تخزين البيانات | 50 |
| اسم المفتاح | 50 |
| النطاق | 50 |
| البيانات (قيمة المفتاح) | 4,194,304 لكل مفتاح |
حدود البيانات الوصفية
حدود عدد الأحرف في البيانات الوصفية التي يحددها المستخدم.
| المكون | الحد الأقصى لعدد الأحرف |
|---|---|
| اسم المفتاح | 50 |
| القيمة | 250 |
| أزواج المفتاح والقيمة | 300 |
حدود الإنتاجية
تضمن حدود الإنتاجية لكل مفتاح أن الأداء يكون مثاليًا على خوادم Roblox. تنطبق كل حد على كل مفتاح فردي عبر جميع الخوادم في تجربة وتنتعش مع مرور الوقت.
تقوم Roblox بفحص استخدام الحصة المرتبطة بالمفتاح على مدار الـ 60 ثانية الماضية. إذا كان الاستخدام، بما في ذلك الطلب الحالي، ضمن حد الإنتاجية، يتم الموافقة على الطلب. إذا تجاوز الاستخدام الحد، يتم رفض الطلب.
| نوع الطلب | واجهة برمجة التطبيقات لخادم اللعبة | واجهة برمجة التطبيقات لـ Open Cloud | الحد |
|---|---|---|---|
| قراءة | GetAsync() GetVersionAsync() GetVersionAtTimeAsync() ListVersionsAsync() UpdateAsync() | الحصول على إدخال تخزين البيانات | 25 ميغابايت في الدقيقة |
| كتابة | SetAsync() IncrementAsync() UpdateAsync() RemoveAsync() | إنشاء، تحديث، زيادة، إزالة إدخال تخزين البيانات | 4 ميغابايت في الدقيقة |
بالإضافة إلى حدود الإنتاجية المذكورة أعلاه، تنظم Roblox البيانات في أقسام بناءً على مخطط داخلي. نتيجة لذلك، عندما يتلقى خادم الخلفية حجمًا كبيرًا من الطلبات إلى نفس مخزن البيانات، يمكن أن يؤدي ذلك إلى مزيد من التقييد. بغض النظر عن السبب، يظهر التقييد كأخطاء إما DatastoreThrottled أو KeyThrottled، اعتمادًا على ما إذا كانت حد الإنتاجية قد تم تجاوزه لمخزن بيانات واحد أو مفتاح. تنطبق رسائل الخطأ هذه على كل من مخازن البيانات المرتبة والعادية.
حدود التخزين
للحفاظ على استقرار التخزين وقابليته للتوسع، تستخدم مخازن البيانات حدًا على مستوى اللعبة لاستخدامك للتخزين.
يتكون هذا الحد من تخصيص أساسي لكل لعبة بالإضافة إلى تخصيص إضافي بناءً على عدد المستخدمين مدى الحياة. المستخدم مدى الحياة هو أي مستخدم انضم إلى لعبتك مرة واحدة على الأقل.
يتم حساب حد التخزين باستخدام الصيغة التالية إجمالي حد التخزين لأحدث إصدار = 500 ميغابايت + 1 ميغابايت × عدد المستخدمين مدى الحياة.
يتم قياس استخدام التخزين باستخدام الحجم المضغوط لأحدث إصدار من كل مفتاح. تقوم مخازن البيانات تلقائيًا بضغط بياناتك قبل التخزين، لذا تجنب ضغطها مسبقًا بنفسك. يضيف الضغط المسبق عبء عمل غير ضروري على وحدة المعالجة المركزية وقد يقلل من فعالية ضغط مخازن البيانات المدمجة. من خلال تخزين البيانات غير المضغوطة، تستفيد تلقائيًا من التحسينات في خوارزميات ضغط Roblox والتحسينات المستقبلية المستندة إلى المخطط.
فقط أحدث إصدار من كل مفتاح يُحتسب نحو استخدام التخزين الخاص بك. المفاتيح المحذوفة والإصدارات السابقة، على الرغم من أنها لا تزال قابلة للوصول من خلال واجهات برمجة التطبيقات للإصدارات خلال فترة الاحتفاظ بها، لا تُحتسب نحو استخدام التخزين الخاص بك. ومع ذلك، فإن مخازن البيانات المحذوفة من خلال طريقة Open Cloud DeleteDataStore تستمر في احتسابها نحو استخدام التخزين خلال فترة معالجة الحذف التي تستمر 30 يومًا، حتى يتم إزالتها نهائيًا.