Żądania, które wysyłasz do magazynów danych, mogą nie powieść się z powodu słabej łączności lub innych problemów. Aby obsłużyć błędy i zwrócić komunikaty z kodem błędu, owiń funkcje magazynu danych w pcall().
Nieudane wywołanie zapisu, takie jak UpdateAsync(), oznacza, że serwer gry nie otrzymał pomyślnej odpowiedzi. Nie zawsze gwarantuje to, że zapis w zapleczu nie miał miejsca. W niektórych scenariuszach awarii, ostateczny stan zapisu może być nieznany dla wywołującego, dopóki nie zostanie zweryfikowany za pomocą kolejnego odczytu bez pamięci podręcznej.
Odniesienie do kodów błędów
| Kod błędu | Nazwa błędu | Komunikat błędu | Uwagi | |
|---|---|---|---|---|
| 101 | KeyNameEmpty | Nazwa klucza nie może być pusta. | Sprawdź, czy klucz wprowadzony do funkcji magazynu danych jest pustym ciągiem. | |
| 102 | KeyNameLimit | Nazwa klucza przekracza limit 50 znaków. | Sprawdź, czy klucz wprowadzony do funkcji magazynu danych przekracza długość 50. | |
| 103 | ValueNotAllowed | Nie można zezwolić na X w DataStore. | Zła funkcja aktualizacji zwróciła wartość typu X. | |
| 104 | CantStoreValue | Nie można przechować X w DataStore. | Funkcja aktualizacji zwróciła wartość typu X, która nie została zserializowana. | |
| 105 | ValueTooLarge | Zserializowana wartość przekracza limit X. | Jeśli ustawiasz wartość za pomocą SetAsync() lub UpdateAsync(), zserializowana długość wartości nie może przekraczać rozmiaru X. Aby sprawdzić zserializowaną długość danych, użyj JSONEncode(). | |
| 106 | MaxValueInvalid | MaxValue musi być liczbą całkowitą. | Jeśli przekazujesz maksymalną wartość do GetSortedAsync() dla OrderedDataStore, musi to być liczba całkowita. | |
| 106 | MinValueInvalid | MinValue musi być liczbą całkowitą. | Jeśli przekazujesz minimalną wartość do GetSortedAsync() dla OrderedDataStore, musi to być liczba całkowita. | |
| 106 | PageSizeGreater | PageSize musi mieścić się w zdefiniowanym zakresie. | Minimalny rozmiar strony dla OrderedDataStore wynosi 1. | |
| 106 | PageSizeLesser | PageSize musi mieścić się w zdefiniowanym zakresie. | Maksymalny rozmiar strony dla OrderedDataStore wynosi 100. | |
| 107 | MinMaxOrderInvalid | MaxValue musi być większe lub równe MinValue. | Maksymalna wartość musi być większa lub równa minimalnej wartości dla GetSortedAsync(). | |
| 301 | GetAsyncThrottle | Żądanie GetAsync zostało odrzucone. Żądanie zostało ograniczone, ale kolejka była pełna. | Żądanie GetAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | |
| 302 | SetAsyncThrottle | Żądanie SetAsync zostało odrzucone. Żądanie zostało ograniczone, ale kolejka była pełna. | Żądanie SetAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | |
| 303 | IncreAsyncThrottle | Żądanie IncrementAsync zostało odrzucone. Żądanie zostało ograniczone, ale kolejka była pełna. | Żądanie IncrementAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | |
| 304 | UpdateAsyncThrottle | Żądanie UpdateAsync zostało odrzucone. Żądanie zostało ograniczone, ale kolejka była pełna. | Żądanie UpdateAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | |
| 304 | TransformThrottle | Żądanie UpdateAsync zostało odrzucone. Żądanie zostało ograniczone, ale kolejka była pełna. | Żądanie UpdateAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | |
| 305 | GetSortedThrottle | Żądanie GetSorted zostało odrzucone. Żądanie zostało ograniczone, ale kolejka była pełna. | Żądanie GetSortedAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | |
| 306 | RemoveAsyncThrottle | Żądanie RemoveAsync zostało odrzucone. Żądanie zostało ograniczone, ale kolejka była pełna. | Żądanie RemoveAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | |
| 401 | DataModelNoAccess | Żądanie nie powiodło się. DataModel jest niedostępny podczas zamykania doświadczenia. | DataModel jest niezainicjowany, ponieważ doświadczenie jest zamykane. | |
| 402 | LuaWebSrvsNoAccess | Żądanie nie powiodło się. LuaWebService jest niedostępny podczas zamykania doświadczenia. | LuaWebService jest niezainicjowany, ponieważ doświadczenie jest zamykane. | |
| 403 | StudioAccessToApisNotAllowed | Nie można pisać do DataStore z poziomu Studio, ponieważ dostęp do API nie jest włączony. | Dostęp do API musi być aktywny, aby używać magazynów danych w Studio. | |
| 404 | InternalError | OrderedDataStore nie istnieje. | OrderedDataStore związany z tym żądaniem nie został znaleziony. Może to być oznaką uszkodzenia danych. Spróbuj ponownie później. | |
| 501 | InternalError | Nie można zanalizować odpowiedzi, ponieważ dane mogą być uszkodzone. | Serwer nie był w stanie zanalizować odpowiedzi na twoje żądanie. Może to być oznaką uszkodzenia danych. Spróbuj ponownie później. | |
| 502 | RequestRejected | Usługi API odrzuciły żądanie z błędem X. | Błąd X wystąpił podczas przetwarzania na serwerach Roblox. Spróbuj ponownie później. | |
| 503 | InternalError | Żądanie magazynu danych zakończyło się sukcesem, ale klucz nie został znaleziony. | Żądany klucz nie został znaleziony w magazynie danych. Może to być oznaką uszkodzenia danych. Spróbuj ponownie później. | |
| 504 | InternalError | Żądanie magazynu danych zakończyło się sukcesem, ale odpowiedź nie była poprawnie sformatowana. | Serwer nie był w stanie zanalizować odpowiedzi na twoje żądanie. Może to być oznaką uszkodzenia danych. Spróbuj ponownie później. | |
| 505 | InternalError | Żądanie OrderedDataStore zakończyło się sukcesem, ale odpowiedź nie była poprawnie sformatowana. | Serwer nie był w stanie zanalizować odpowiedzi na twoje żądanie OrderedDataStore. Może to być oznaką uszkodzenia danych. Spróbuj ponownie później. | |
| 509 | OperationNotAllowed | Operacje magazynu danych są zablokowane podczas działania na osobistym RCC, aby zapobiec możliwemu uszkodzeniu danych. | Pisanie do magazynu danych jest zablokowane na prywatnych kanałach RCC. | |
| 511 | AttributeSizeTooLarge | Rozmiar atrybutu metadanych przekracza limit X. | Rozmiar zserializowanej metadanych przekracza limit X. Wartość X jest dynamiczna. Jeśli rozmiar się zmienia, wartość również się zmienia. | |
| 512 | UserIdLimitExceeded | Rozmiar UserID przekracza limit X. | Długość tablicy identyfikatorów użytkowników dostarczonej przez użytkownika przekracza limit X. | |
| 513 | AttributeFormatError | Format atrybutu userId jest nieprawidłowy. | Dostarczony identyfikator użytkownika nie jest liczbą. | |
| 513 | AttributeFormatError | Format metadanych atrybutu jest nieprawidłowy. | Metadane nie są tabelą. | |
| GetVersionAsyncThrottle | Żądanie GetVersionAsync zostało odrzucone. Żądanie zostało ograniczone. | Żądanie GetVersionAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | ||
| GetVersionAtTimeAsyncThrottle | Żądanie GetVersionAtTimeAsync zostało odrzucone. Żądanie zostało ograniczone. | Żądanie GetVersionAtTimeAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | ||
| ListDataStoresAsyncThrottle | Żądanie ListDataStoresAsync zostało odrzucone. Żądanie zostało ograniczone. | Żądanie ListDataStoresAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | ||
| ListKeysAsyncThrottle | Żądanie ListKeysAsync zostało odrzucone. Żądanie zostało ograniczone. | Żądanie ListKeysAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | ||
| ListVersionsAsyncThrottle | Żądanie ListVersionsAsync zostało odrzucone. Żądanie zostało ograniczone. | Żądanie ListVersionsAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | ||
| RemoveVersionAsyncThrottle | Żądanie RemoveVersionAsync zostało odrzucone. Żądanie zostało ograniczone. | Żądanie RemoveVersionAsync() przekroczyło maksymalny rozmiar kolejki i Roblox nie jest w stanie przetworzyć żądań przy obecnym przepustowości. | ||
| InvalidTimestamp | Znacznik czasu musi być dodatni i nie może być dłuższy niż dziesięć minut w przyszłości. | Dostarczony znacznik czasu do GetVersionAtTimeAsync() był nieprawidłowy. | ||
| StandardReadExperienceThrottled | Żądanie StandardRead zostało ograniczone przez limity doświadczenia. | Żądanie do GetAsync(), GetVersionAsync(), GetVersionAtTimeAsync(), lub odczyt UpdateAsync() na standardowym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia StandardRead. | ||
| StandardWriteExperienceThrottled | Żądanie StandardWrite zostało ograniczone przez limity doświadczenia. | Żądanie do SetAsync(), IncrementAsync(), lub zapis UpdateAsync() na standardowym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia StandardWrite. | ||
| StandardListExperienceThrottled | Żądanie StandardList zostało ograniczone przez limity doświadczenia. | Żądanie do ListKeysAsync(), ListVersionsAsync(), lub ListDataStoresAsync() na standardowych magazynach danych przekroczyło limit przepustowości na poziomie doświadczenia StandardList. | ||
| StandardRemoveExperienceThrottled | Żądanie StandardRemove zostało ograniczone przez limity doświadczenia. | Żądanie do RemoveAsync() na standardowym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia StandardRemove. | ||
| OrderedReadExperienceThrottled | Żądanie OrderedRead zostało ograniczone przez limity doświadczenia. | Żądanie do GetAsync(), BatchGetAsync(), lub odczyt UpdateAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia OrderedRead. | ||
| OrderedWriteExperienceThrottled | Żądanie OrderedWrite zostało ograniczone przez limity doświadczenia. | Żądanie do SetAsync(), IncrementAsync(), lub zapis UpdateAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia OrderedWrite. | ||
| OrderedListExperienceThrottled | Żądanie OrderedList zostało ograniczone przez limity doświadczenia. | Żądanie do GetSortedAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia OrderedList. | ||
| OrderedRemoveExperienceThrottled | Żądanie OrderedRemove zostało ograniczone przez limity doświadczenia. | Żądanie do RemoveAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia OrderedRemove. | ||
| StandardReadGameServerThrottled | Żądanie StandardRead zostało ograniczone przez limity serwera gry lub kolejka żądań była pełna. | Żądanie do GetAsync(), GetVersionAsync(), GetVersionAtTimeAsync(), lub odczyt UpdateAsync() na standardowym magazynie danych przekroczyło limit przepustowości na poziomie serwera gry StandardRead. | ||
| StandardWriteGameServerThrottled | Żądanie StandardWrite zostało ograniczone przez limity serwera gry lub kolejka żądań była pełna. | Żądanie do SetAsync(), IncrementAsync(), lub zapis UpdateAsync() na standardowym magazynie danych przekroczyło limit przepustowości na poziomie serwera gry StandardWrite. | ||
| StandardListGameServerThrottled | Żądanie StandardList zostało ograniczone przez limity serwera gry lub kolejka żądań była pełna. | Żądanie do ListKeysAsync(), ListVersionsAsync(), lub ListDataStoresAsync() na standardowych magazynach danych przekroczyło limit przepustowości na poziomie serwera gry StandardList. | ||
| StandardRemoveGameServerThrottled | Żądanie StandardRemove zostało ograniczone przez limity serwera gry lub kolejka żądań była pełna. | Żądanie do RemoveAsync() na standardowym magazynie danych przekroczyło limit przepustowości na poziomie serwera gry StandardRemove. | ||
| OrderedReadGameServerThrottled | Żądanie OrderedRead zostało ograniczone przez limity serwera gry lub kolejka żądań była pełna. | Żądanie do GetAsync(), BatchGetAsync(), lub odczyt UpdateAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie serwera gry OrderedRead. | ||
| OrderedWriteGameServerThrottled | Żądanie OrderedWrite zostało ograniczone przez limity serwera gry lub kolejka żądań była pełna. | Żądanie do SetAsync(), IncrementAsync(), lub zapis UpdateAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie serwera gry OrderedWrite. | ||
| OrderedListGameServerThrottled | Żądanie OrderedList zostało ograniczone przez limity serwera gry lub kolejka żądań była pełna. | Żądanie do GetSortedAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie serwera gry OrderedList. | ||
| OrderedRemoveGameServerThrottled | Żądanie OrderedRemove zostało ograniczone przez limity serwera gry lub kolejka żądań była pełna. | Żądanie do RemoveAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie serwera gry OrderedRemove. |
Kody błędów serwera
| Nazwa błędu | Komunikat błędu | Uwagi |
|---|---|---|
| DatastoreDeleted | Magazyn danych został usunięty. | Operacja na magazynie danych nie mogła się odbyć, ponieważ magazyn danych został wcześniej usunięty. |
| DatastoreThrottled | Wskaźnik żądań przekracza dozwolony maksymalny dla datastore. | Zbyt wiele żądań zostało wysłanych do jednego magazynu danych. |
| InternalServerError | Wystąpił wewnętrzny błąd serwera. | Okazjonalny błąd na serwerach Roblox. Spróbuj ponownie, najlepiej z wykładniczym opóźnieniem. |
| InvalidExclusiveStartKey | Dostarczony klucz startowy jest nieprawidłowy. | Dostarczony klucz startowy (kursor) do operacji listowania, takiej jak ListKeysAsync(), jest nieprawidłowy. |
| InvalidPlace | Dostarczone miejsce jest nieprawidłowe. | Brak pasującego identyfikatora uniwersum dla miejsca. Spróbuj ponownie później. |
| InvalidTarget | Dostarczony cel jest nieprawidłowy. | Nazwa klucza zamówionego magazynu danych przekracza limit 50 znaków. |
| InvalidUniverse | Dostarczone uniwersum jest nieprawidłowe. | Brak pasującego identyfikatora miejsca dla uniwersum. Spróbuj ponownie później. |
| InvalidUserIds | Dostarczone identyfikatory użytkowników mają nieprawidłowy format. | Nie udało się zanalizować identyfikatorów użytkowników. |
| KeyThrottled | Wskaźnik żądań przekracza dozwolony maksymalny dla klucza. | Wskaźnik żądań przekracza maksymalny dozwolony wskaźnik żądań dla pojedynczego klucza. |
| KeyNotFound | Żądany klucz nie istnieje. | Klucz nie istnieje. |
| N/A | Brak stron do przejścia. | Ten błąd występuje, gdy wywołujesz Pages:AdvanceToNextPageAsync() na ostatniej stronie. |
| StandardReadExperienceThrottled | Wskaźnik żądań standardowego odczytu przekracza dozwolony maksymalny dla doświadczenia. | Żądanie do GetAsync(), GetVersionAsync(), GetVersionAtTimeAsync(), lub odczyt UpdateAsync() na standardowym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia StandardRead. |
| StandardWriteExperienceThrottled | Wskaźnik żądań standardowego zapisu przekracza dozwolony maksymalny dla doświadczenia. | Żądanie do SetAsync(), IncrementAsync(), lub zapis UpdateAsync() na standardowym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia StandardWrite. |
| StandardListExperienceThrottled | Wskaźnik żądań standardowego listowania przekracza dozwolony maksymalny dla doświadczenia. | Żądanie do ListKeysAsync(), ListVersionsAsync(), lub ListDataStoresAsync() na standardowych magazynach danych przekroczyło limit przepustowości na poziomie doświadczenia StandardList. |
| StandardRemoveExperienceThrottled | Wskaźnik żądań standardowego usuwania przekracza dozwolony maksymalny dla doświadczenia. | Żądanie do RemoveAsync() na standardowym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia StandardRemove. |
| OrderedReadExperienceThrottled | Wskaźnik żądań zamówionego odczytu przekracza dozwolony maksymalny dla doświadczenia. | Żądanie do GetAsync(), BatchGetAsync(), lub odczyt UpdateAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia OrderedRead. |
| OrderedWriteExperienceThrottled | Wskaźnik żądań zamówionego zapisu przekracza dozwolony maksymalny dla doświadczenia. | Żądanie do SetAsync(), IncrementAsync(), lub zapis UpdateAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia OrderedWrite. |
| OrderedListExperienceThrottled | Wskaźnik żądań zamówionego listowania przekracza dozwolony maksymalny dla doświadczenia. | Żądanie do GetSortedAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia OrderedList. |
| OrderedRemoveExperienceThrottled | Wskaźnik żądań zamówionego usuwania przekracza dozwolony maksymalny dla doświadczenia. | Żądanie do RemoveAsync() na zamówionym magazynie danych przekroczyło limit przepustowości na poziomie doświadczenia OrderedRemove. |
Limity
Modele danych mają limity. Jeśli doświadczenie przekroczy te limity, usługa automatycznie ogranicza użycie magazynu danych doświadczenia i powoduje, że przyszłe żądania są umieszczane w jednej z następujących kolejek:
- Ustaw
- Zamówione ustawienie
- Odczyt
- Zamówiony odczyt
Żądania w kolejce są obsługiwane w kolejności, w jakiej zostały odebrane. Wywołana funkcja nadal będzie czekać, dopóki jej żądanie jest nadal w kolejce. Jeśli klucz magazynu danych jest ograniczony, żądanie jest umieszczane w kolejce, ale jest tymczasowo pomijane.
Każda kolejka ma limit 30 żądań. Gdy limit kolejki zostanie osiągnięty, żądania kończą się niepowodzeniem z kodem błędu w zakresie 301-306, co wskazuje, że żądania zostały całkowicie odrzucone.
Limity dostępu
Magazyny danych podlegają zarówno limitem doświadczenia, jak i serwera. Limity na poziomie doświadczenia skalują się w zależności od całkowitej liczby jednoczesnych użytkowników w doświadczeniu, podczas gdy limity na poziomie serwera są konfigurowalne i mają być używane jako narzędzie przez twórcę.
Limity doświadczenia
Każde doświadczenie ma dozwoloną określoną liczbę żądań magazynu danych w zależności od typu magazynu danych, typu żądania i liczby jednoczesnych użytkowników. Dla każdego typu magazynu danych i typu żądania limit jest dzielony między wszystkie wymienione funkcje.
- UpdateAsync() zużywa zarówno budżet żądań odczytu, jak i zapisu. Pojedyncze wywołanie zmniejszy oba limity.
- Serwer gry i Open Cloud dzielą budżet; ruch Open Cloud może być ograniczany przez użycie w doświadczeniu (i odwrotnie). Zobacz Kontroluj limity przepustowości w celu uzyskania dalszych wskazówek.
Standardowe magazyny danych
| Typ żądania | API serwera gry | API Open Cloud | Wspólne limity (żądania na minutę) |
|---|---|---|---|
| Odczyt | GetAsync() GetVersionAsync() GetVersionAtTimeAsync() UpdateAsync() | Pobierz wpis magazynu danych | 300 + liczbaUżytkowników × 40 |
| Zapis | SetAsync() IncrementAsync() UpdateAsync() | Utwórz, zaktualizuj, zwiększ wpis magazynu danych | 300 + liczbaUżytkowników × 20 |
| Lista | ListDataStoresAsync() ListKeysAsync() ListVersionsAsync() | Lista magazynów danych, lista wpisów magazynu danych, lista rewizji wpisów magazynu danych | 300 + liczbaUżytkowników × 2 |
| Usuń | RemoveAsync() | Usuń wpis magazynu danych, usuń magazyn danych, przywróć magazyn danych | 300 + liczbaUżytkowników × 40 |
Zamówione magazyny danych
| Typ żądania | API serwera gry | API Open Cloud | Wspólne limity (żądania na minutę) |
|---|---|---|---|
| Odczyt | GetAsync() BatchGetAsync() UpdateAsync() | Pobierz wpis zamówionego magazynu danych | 300 + liczbaUżytkowników × 40 |
| Zapis | SetAsync() IncrementAsync() UpdateAsync() | Utwórz, zaktualizuj, zwiększ wpis zamówionego magazynu danych | 300 + liczbaUżytkowników × 20 |
| Lista | GetSortedAsync() | Lista wpisów zamówionego magazynu danych | 300 + liczbaUżytkowników × 2 |
| Usuń | RemoveAsync() | Usuń wpis zamówionego magazynu danych | 300 + liczbaUżytkowników × 40 |
Kontroluj limity przepustowości
Ponieważ żądania Open Cloud i serwera gry są współdzielone, ważne jest, aby niezależnie kontrolować, ile każde z nich może zużywać z budżetu.
Serwer gry
Poszczególne serwery mają wbudowane limity, jak opisano powyżej. Użyj kombinacji SetRateLimitForRequestType() i GetRequestBudgetForRequestType(), aby utrzymać szczegółową kontrolę nad wkładem poszczególnych serwerów w całkowity budżet.
Open Cloud
Żądania Open Cloud wymagają zewnętrznego rozwiązania do ograniczania przepustowości. Zalecamy jedno z następujących podejść:
- (Proste) Dodaj krótki czas oczekiwania po każdym żądaniu, szczególnie jeśli wywołujesz to samo API w ciągłej pętli. Ustaw ten czas oczekiwania równy 60 / (pożądana konsumpcja budżetu na minutę) sekund, jako górną granicę. Zauważ, że to podejście nie pozwala na wysyłanie żądań w wybuchach.
- (Solidne) Zaimplementuj lokalny ogranicznik przepustowości, korzystając ze strategii leaky bucket.
Poniższe przykłady kodu Node.js zawierają implementacje referencyjne.
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('Zmienna środowiskowa API_KEY nie jest ustawiona.');
}
const apiHeaderKey = 'x-api-key';
const universeId = '';
const dataStoreId = 'Inventory';
const baseUrl = 'https://apis.roblox.com/cloud/v2/';
// --- Konfiguracja ograniczania przepustowości na operację (żądania na minutę) ---
const LIST_RATE_PER_MIN = 60;
const GET_RATE_PER_MIN = 120;
const UPDATE_RATE_PER_MIN = 60;
// Górna granica odstępu na operację: 60 / (żądania na minutę) sekundy.
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));
// Wykonuje żądanie, a następnie czeka na własny odstęp tej operacji przed zwróceniem.
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) // Ciało musi być ciągiem
}, 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(`\nPrzetwarzanie wpisu: ${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(`Odpowiedź: ${await updateResponse.text()}`);
}
} catch (error) {
console.error('Wystąpił błąd podczas wykonywania:', error);
}
})();Limity serwera
Każdy serwer ma konfigurowalny limit przepustowości dla każdego typu żądania, w zależności od liczby graczy na tym serwerze. Serwery otrzymują jednorazowy wybuch dodatkowego budżetu żądań, gdy są po raz pierwszy tworzone. Użyj GetRequestBudgetForRequestType(), aby potwierdzić liczbę żądań magazynu danych, które bieżący serwer może wykonać w danym momencie.
Te limity są konfigurowalne przez twórcę za pomocą API SetRateLimitForRequestType(). Używając tego API, twórca może skonfigurować własne limity przepustowości magazynów danych dla każdego typu żądania.
Poniższe domyślne limity przepustowości mają zastosowanie, jeśli API nie jest wywoływane:
Standardowe magazyny danych
| Typ żądania | DataStoreRequestType Enum | API serwera gry | Żądania na minutę |
|---|---|---|---|
| Odczyt | StandardRead | GetAsync() GetVersionAsync() GetVersionAtTimeAsync() UpdateAsync() | 60 + liczbaGraczy × 40 |
| Zapis | StandardWrite | SetAsync() IncrementAsync() UpdateAsync() | 60 + liczbaGraczy × 40 |
| Lista | StandardList | ListDataStoresAsync() ListKeysAsync() ListVersionsAsync() | 5 + liczbaGraczy × 2 |
| Usuń | StandardRemove | RemoveAsync() | 60 + liczbaGraczy × 40 |
| Usuń wersję (przestarzałe) | RemoveVersionAsync | RemoveVersionAsync() | 5 + liczbaGraczy × 2 |
Zamówione magazyny danych
| Typ żądania | DataStoreRequestType Enum | API serwera gry | Żądania na minutę |
|---|---|---|---|
| Odczyt | OrderedRead | GetAsync() BatchGetAsync() UpdateAsync() | 60 + liczbaGraczy × 40 |
| Zapis | OrderedWrite | SetAsync() IncrementAsync() UpdateAsync() | 30 + liczbaGraczy × 5 |
| Lista | OrderedList | GetSortedAsync() | 5 + liczbaGraczy × 2 |
| Usuń | OrderedRemove | RemoveAsync() | 30 + liczbaGraczy × 5 |
Limity danych
Magazyny danych ograniczają, ile danych można używać na wpis.
Nazwa magazynu danych, nazwa klucza i zakres muszą być wszystkie poniżej określonej długości znaków. Użyj string.len(), aby sprawdzić ich długość.
Dane (wartość klucza) są również przechowywane jako ciąg, niezależnie od ich początkowego typu. Możesz sprawdzić rozmiar danych za pomocą funkcji JSONEncode(), która konwertuje dane Luau na zserializowaną tabelę JSON.
| Komponent | Maksymalna liczba znaków |
|---|---|
| Nazwa magazynu danych | 50 |
| Nazwa klucza | 50 |
| Zakres | 50 |
| Dane (wartość klucza) | 4,194,304 na klucz |
Limity metadanych
Limity dotyczące liczby znaków w zdefiniowanej przez użytkownika metadanych.
| Komponent | Maksymalna liczba znaków |
|---|---|
| Nazwa klucza | 50 |
| Wartość | 250 |
| Pary klucz-wartość | 300 |
Limity przepustowości
Limity przepustowości na poziomie klucza zapewniają, że wydajność jest optymalna na serwerach Roblox. Każdy limit dotyczy każdego pojedynczego klucza we wszystkich serwerach w doświadczeniu i odnawia się w czasie.
Roblox bada wykorzystanie kwoty związanej z kluczem w ciągu ostatnich 60 sekund. Jeśli wykorzystanie, w tym bieżące żądanie, mieści się w limicie przepustowości, żądanie jest zatwierdzane. Jeśli wykorzystanie przekracza limit, żądanie jest odrzucane.
| Typ żądania | API serwera gry | API Open Cloud | Limit |
|---|---|---|---|
| Odczyt | GetAsync() GetVersionAsync() GetVersionAtTimeAsync() ListVersionsAsync() UpdateAsync() | Pobierz wpis magazynu danych | 25 MB na minutę |
| Zapis | SetAsync() IncrementAsync() UpdateAsync() RemoveAsync() | Utwórz, zaktualizuj, zwiększ, usuń wpis magazynu danych | 4 MB na minutę |
Oprócz powyższych limitów przepustowości, Roblox organizuje dane w partycjach na podstawie wewnętrznego schematu. W rezultacie, gdy serwer zaplecza otrzymuje dużą liczbę żądań do tego samego magazynu danych, może to prowadzić do dalszego ograniczania. Niezależnie od przyczyny, ograniczenie objawia się jako błędy DatastoreThrottled lub KeyThrottled, w zależności od tego, czy limit przepustowości został przekroczony dla pojedynczego magazynu danych, czy klucza. Te komunikaty o błędach dotyczą zarówno uporządkowanych, jak i standardowych magazynów danych.
Limity przechowywania
Aby utrzymać stabilność i skalowalność przechowywania, magazyny danych używają limitu na poziomie gry dla twojego wykorzystania przechowywania.
Limit ten składa się z podstawowej alokacji dla każdej gry oraz dodatkowej alokacji w oparciu o liczbę użytkowników w całym okresie. Użytkownik w całym okresie to każdy użytkownik, który dołączył do twojej gry przynajmniej raz.
Limit przechowywania oblicza się za pomocą następującego wzoru Całkowity limit przechowywania najnowszej wersji = 500 MB + 1 MB × liczba użytkowników w całym okresie.
Wykorzystanie przechowywania mierzy się za pomocą skompresowanego rozmiaru najnowszej wersji każdego klucza. Magazyny danych automatycznie kompresują twoje dane przed przechowaniem, więc unikaj wstępnej kompresji. Wstępna kompresja dodaje niepotrzebne obciążenie CPU i może zmniejszyć skuteczność wbudowanej kompresji magazynów danych. Przechowując nieskompresowane dane, automatycznie korzystasz z ulepszeń algorytmów kompresji Robloxa i przyszłych optymalizacji opartych na schematach.
Tylko najnowsza wersja każdego klucza liczy się do twojego wykorzystania przechowywania. Usunięte klucze i zastąpione wersje, chociaż nadal dostępne przez API wersji w czasie ich okresu przechowywania, nie liczą się do twojego wykorzystania przechowywania. Jednak magazyny danych usunięte za pomocą metody Open Cloud DeleteDataStore nadal liczą się do wykorzystania przechowywania w czasie ich 30-dniowego okresu przetwarzania usunięcia, aż do ich trwałego usunięcia.