Client Configurations + Auto-Retry on HTTP Request Failure #31
@ -8,31 +8,33 @@ local tokens = {
|
|||||||
local Utils = require(script.Parent.Utils)
|
local Utils = require(script.Parent.Utils)
|
||||||
local MarcSyncClient = {}
|
local MarcSyncClient = {}
|
||||||
|
|
||||||
|
local Types = require(script.Parent.Types)
|
||||||
|
|
||||||
MarcSyncClient.getVersion = function(self:typeof(MarcSyncClient), clientId: number?):string
|
MarcSyncClient.getVersion = function(self:typeof(MarcSyncClient), clientId: number?):string
|
||||||
self:_checkInstallation()
|
self:_checkInstallation()
|
||||||
local url = ""
|
local url = ""
|
||||||
if clientId then url = "/"..clientId end
|
if clientId then url = "/"..clientId end
|
||||||
local result = Utils.makeHTTPRequest("GET", "https://api.marcsync.dev/v0/utils/version"..url);
|
local result = Utils.makeHTTPRequest("", "GET", "https://api.marcsync.dev/v0/utils/version"..url, nil, nil, self._options);
|
||||||
return result["version"]
|
return result["version"]
|
||||||
end
|
end
|
||||||
|
|
||||||
MarcSyncClient.createCollection = function(self:typeof(MarcSyncClient), collectionName: string):typeof(require(script.Parent.Objects.Collection).new())
|
MarcSyncClient.createCollection = function(self:typeof(MarcSyncClient), collectionName: string):typeof(require(script.Parent.Objects.Collection).new())
|
||||||
if not self._accessToken then error("[MarcSync] Please set a Token before using MarcSync.") end
|
if not self._accessToken then error("[MarcSync] Please set a Token before using MarcSync.") end
|
||||||
if not collectionName then error("No CollectionName Provided") end
|
if not collectionName then error("No CollectionName Provided") end
|
||||||
local result = Utils.makeHTTPRequest("collection", "POST", "https://api.marcsync.dev/v0/collection/"..collectionName, {}, self._accessToken);
|
local result = Utils.makeHTTPRequest("collection", "POST", "https://api.marcsync.dev/v0/collection/"..collectionName, {}, self._accessToken, self._options);
|
||||||
|
|
||||||
if not result["success"] then error(result["errorMessage"]) end
|
if not result["success"] then error(result["errorMessage"]) end
|
||||||
result = require(script.Parent.Objects.Collection).new(collectionName, self._accessToken)
|
result = require(script.Parent.Objects.Collection).new(collectionName, self._accessToken, self._options)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
MarcSyncClient.fetchCollection = function(self:typeof(MarcSyncClient), collectionName: string):typeof(require(script.Parent.Objects.Collection).new())
|
MarcSyncClient.fetchCollection = function(self:typeof(MarcSyncClient), collectionName: string):typeof(require(script.Parent.Objects.Collection).new())
|
||||||
self:_checkInstallation()
|
self:_checkInstallation()
|
||||||
if not collectionName then error("No CollectionName Provided") end
|
if not collectionName then error("No CollectionName Provided") end
|
||||||
local result = Utils.makeHTTPRequest("collection", "GET", "https://api.marcsync.dev/v0/collection/"..collectionName, {}, self._accessToken);
|
local result = Utils.makeHTTPRequest("collection", "GET", "https://api.marcsync.dev/v0/collection/"..collectionName, {}, self._accessToken, self._options);
|
||||||
|
|
||||||
if not result["success"] then error(result["errorMessage"]) end
|
if not result["success"] then error(result["errorMessage"]) end
|
||||||
result = require(script.Parent.Objects.Collection).new(collectionName, self._accessToken)
|
result = require(script.Parent.Objects.Collection).new(collectionName, self._accessToken, self._options)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
@ -40,15 +42,16 @@ MarcSyncClient.getCollection = function(self:typeof(MarcSyncClient), collectionN
|
|||||||
if typeof(self) ~= "table" then error("Please use : instead of .") end
|
if typeof(self) ~= "table" then error("Please use : instead of .") end
|
||||||
self:_checkInstallation()
|
self:_checkInstallation()
|
||||||
if not collectionName then error("No CollectionName Provided") end
|
if not collectionName then error("No CollectionName Provided") end
|
||||||
return require(script.Parent.Objects.Collection).new(collectionName, self._accessToken)
|
return require(script.Parent.Objects.Collection).new(collectionName, self._accessToken, self._options)
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
new = function(accessToken: string):typeof(MarcSyncClient)
|
new = function(accessToken: string, options: Types.ClientOptions?):typeof(MarcSyncClient)
|
||||||
if not accessToken then warn("Token not provided while creating a new MarcSync Object.") end
|
if not accessToken then warn("Token not provided while creating a new MarcSync Object.") end
|
||||||
if not tokens[accessToken] then warn("Token provided for creating a new MarcSync Object not Found in Token Table, using it as token instead.") else accessToken = tokens[accessToken] end
|
if not tokens[accessToken] then warn("Token provided for creating a new MarcSync Object not Found in Token Table, using it as token instead.") else accessToken = tokens[accessToken] end
|
||||||
local self = {}
|
local self = {}
|
||||||
self._accessToken = accessToken
|
self._accessToken = accessToken
|
||||||
|
self._options = options or {retryCount = 3}
|
||||||
self._checkInstallation = function()
|
self._checkInstallation = function()
|
||||||
if not self then error("Please Setup MarcSync before using MarcSync.") end
|
if not self then error("Please Setup MarcSync before using MarcSync.") end
|
||||||
if not self._accessToken then error("[MarcSync] Please set a Token before using MarcSync.") end
|
if not self._accessToken then error("[MarcSync] Please set a Token before using MarcSync.") end
|
@ -7,11 +7,11 @@ local Collection = {}
|
|||||||
|
|
||||||
Collection.createEntry = function(self:typeof(Collection), data:Types.EntryData):typeof(Entry.new())
|
Collection.createEntry = function(self:typeof(Collection), data:Types.EntryData):typeof(Entry.new())
|
||||||
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
||||||
local result = Utils.makeHTTPRequest("entry", "POST", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["data"]=data}, self._accessToken);
|
local result = Utils.makeHTTPRequest("entry", "POST", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["data"]=data}, self._accessToken, self._options);
|
||||||
|
|
||||||
if result["success"] and result["objectId"] then
|
if result["success"] and result["objectId"] then
|
||||||
data["_id"] = result["objectId"]
|
data["_id"] = result["objectId"]
|
||||||
result = require(script.Parent.Entry).new(self._collectionName, data, self._accessToken)
|
result = require(script.Parent.Entry).new(self._collectionName, data, self._accessToken, self._options)
|
||||||
else
|
else
|
||||||
error(result["errorMessage"])
|
error(result["errorMessage"])
|
||||||
end
|
end
|
||||||
@ -21,7 +21,7 @@ end
|
|||||||
|
|
||||||
Collection.updateEntries = function(self:typeof(Collection), filters:Types.EntryData, data:Types.EntryData):number
|
Collection.updateEntries = function(self:typeof(Collection), filters:Types.EntryData, data:Types.EntryData):number
|
||||||
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
||||||
local result = Utils.makeHTTPRequest("entry", "PUT", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["filters"]=filters,["data"]=data}, self._accessToken);
|
local result = Utils.makeHTTPRequest("entry", "PUT", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["filters"]=filters,["data"]=data}, self._accessToken, self._options);
|
||||||
if not result["success"] then error(result["errorMessage"]) end
|
if not result["success"] then error(result["errorMessage"]) end
|
||||||
|
|
||||||
return result["modifiedEntries"]
|
return result["modifiedEntries"]
|
||||||
@ -30,11 +30,11 @@ end
|
|||||||
Collection.getEntries = function(self:typeof(Collection), filters:Types.EntryData):{[number]:typeof(Entry.new())}
|
Collection.getEntries = function(self:typeof(Collection), filters:Types.EntryData):{[number]:typeof(Entry.new())}
|
||||||
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
||||||
if not filters then filters = {} end
|
if not filters then filters = {} end
|
||||||
local result = Utils.makeHTTPRequest("entry", "DELETE", "https://api.marcsync.dev/v0/entries/"..self._collectionName.."?isQuery=true", {["filters"]=filters}, self._accessToken);
|
local result = Utils.makeHTTPRequest("entry", "DELETE", "https://api.marcsync.dev/v0/entries/"..self._collectionName.."?isQuery=true", {["filters"]=filters}, self._accessToken, self._options);
|
||||||
if result["success"] and result["entries"] then
|
if result["success"] and result["entries"] then
|
||||||
local _result = {}
|
local _result = {}
|
||||||
for index,entry in pairs(result["entries"]) do
|
for index,entry in pairs(result["entries"]) do
|
||||||
_result[index] = require(script.Parent.Entry).new(self._collectionName, entry, self._accessToken)
|
_result[index] = require(script.Parent.Entry).new(self._collectionName, entry, self._accessToken, self._options)
|
||||||
end
|
end
|
||||||
result = _result
|
result = _result
|
||||||
else
|
else
|
||||||
@ -46,7 +46,7 @@ end
|
|||||||
|
|
||||||
Collection.deleteEntries = function(self:typeof(Collection), filters:Types.EntryData):number
|
Collection.deleteEntries = function(self:typeof(Collection), filters:Types.EntryData):number
|
||||||
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
||||||
local result = Utils.makeHTTPRequest("DELETE", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["filters"]=filters}, self._accessToken);
|
local result = Utils.makeHTTPRequest("DELETE", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["filters"]=filters}, self._accessToken, self._options);
|
||||||
if not result["success"] then error(result["errorMessage"]) end
|
if not result["success"] then error(result["errorMessage"]) end
|
||||||
|
|
||||||
return result["deletedEntries"]
|
return result["deletedEntries"]
|
||||||
@ -54,16 +54,17 @@ end
|
|||||||
|
|
||||||
Collection.drop = function(self:typeof(Collection))
|
Collection.drop = function(self:typeof(Collection))
|
||||||
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end
|
||||||
local result = Utils.makeHTTPRequest("collection", "DELETE", "https://api.marcsync.dev/v0/collection/"..self._collectionName, {}, self._accessToken);
|
local result = Utils.makeHTTPRequest("collection", "DELETE", "https://api.marcsync.dev/v0/collection/"..self._collectionName, {}, self._accessToken, self._options);
|
||||||
if not result["success"] then error(result["errorMessage"]) end
|
if not result["success"] then error(result["errorMessage"]) end
|
||||||
self = nil
|
self = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
new = function(collectionName: string, accessToken: string):typeof(Collection)
|
new = function(collectionName: string, accessToken: string, options: Types.ClientOptions):typeof(Collection)
|
||||||
local self = {}
|
local self = {}
|
||||||
self._collectionName = collectionName
|
self._collectionName = collectionName
|
||||||
self._accessToken = accessToken
|
self._accessToken = accessToken
|
||||||
|
self._options = options
|
||||||
|
|
||||||
self = setmetatable(self, {
|
self = setmetatable(self, {
|
||||||
__index = Collection
|
__index = Collection
|
||||||
|
@ -14,7 +14,7 @@ Entry.getValues = function(self:typeof(Entry)):Types.EntryData
|
|||||||
end
|
end
|
||||||
|
|
||||||
Entry.updateValues = function(self:typeof(Entry), data:Types.EntryData):number
|
Entry.updateValues = function(self:typeof(Entry), data:Types.EntryData):number
|
||||||
local result = Utils.makeHTTPRequest("entry", "PUT", "https://api.marcsync.dev/v0/entries/"..self._tableId, {["filters"]={["_id"]=self._objectId},["data"]=data}, self._accessToken);
|
local result = Utils.makeHTTPRequest("entry", "PUT", "https://api.marcsync.dev/v0/entries/"..self._tableId, {["filters"]={["_id"]=self._objectId},["data"]=data}, self._accessToken, self._options);
|
||||||
|
|
||||||
if result["success"] and result["modifiedEntries"] and result["modifiedEntries"] > 0 then
|
if result["success"] and result["modifiedEntries"] and result["modifiedEntries"] > 0 then
|
||||||
for i,v in pairs(data) do
|
for i,v in pairs(data) do
|
||||||
@ -29,7 +29,7 @@ end
|
|||||||
|
|
||||||
Entry.delete = function(self:typeof(Entry))
|
Entry.delete = function(self:typeof(Entry))
|
||||||
if typeof(self) ~= "table" then error("Please use : instead of .") end
|
if typeof(self) ~= "table" then error("Please use : instead of .") end
|
||||||
local result = Utils.makeHTTPRequest("entry", "DELETE", "https://api.marcsync.dev/v0/entries/"..self._tableId, {["filters"]={["_id"]=self._objectId}}, self._accessToken);
|
local result = Utils.makeHTTPRequest("entry", "DELETE", "https://api.marcsync.dev/v0/entries/"..self._tableId, {["filters"]={["_id"]=self._objectId}}, self._accessToken, self._options);
|
||||||
|
|
||||||
if not result["success"] then error(result["errorMessage"]) end
|
if not result["success"] then error(result["errorMessage"]) end
|
||||||
self = nil
|
self = nil
|
||||||
@ -37,13 +37,14 @@ Entry.delete = function(self:typeof(Entry))
|
|||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
new = function(tableId:string, entryData:Types.EntryData, accessToken:string):typeof(Entry)
|
new = function(tableId:string, entryData:Types.EntryData, accessToken:string, options: Types.ClientOptions):typeof(Entry)
|
||||||
if not tableId or not entryData or not entryData["_id"] or not accessToken then error("[MarcSync: Entry] Tried creating invalid Entry Object.") end
|
if not tableId or not entryData or not entryData["_id"] or not accessToken then error("[MarcSync: Entry] Tried creating invalid Entry Object.") end
|
||||||
local self = {}
|
local self = {}
|
||||||
self._tableId = tableId
|
self._tableId = tableId
|
||||||
self._entryData = entryData
|
self._entryData = entryData
|
||||||
self._objectId = entryData["_id"]
|
self._objectId = entryData["_id"]
|
||||||
self._accessToken = accessToken
|
self._accessToken = accessToken
|
||||||
|
self._options = options
|
||||||
|
|
||||||
self = setmetatable(self, {
|
self = setmetatable(self, {
|
||||||
__index = Entry
|
__index = Entry
|
||||||
|
@ -4,4 +4,8 @@ export type EntryData = {
|
|||||||
[string]: any
|
[string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ClientOptions = {
|
||||||
|
retryCount: number
|
||||||
|
}
|
||||||
|
|
||||||
return types
|
return types
|
@ -3,8 +3,9 @@ local CollectionError = require(script.Parent.Errors.Collection)
|
|||||||
local EntryError = require(script.Parent.Errors.Entry)
|
local EntryError = require(script.Parent.Errors.Entry)
|
||||||
|
|
||||||
local HttpService = game:GetService("HttpService")
|
local HttpService = game:GetService("HttpService")
|
||||||
|
local Types = require(script.Parent.Types)
|
||||||
|
|
||||||
function errorHandler(type: string, resultBody: any, resultObject: {})
|
function errorHandler(callInformation: {}, resultBody: any, resultObject: {}, retryCount: number)
|
||||||
local Error;
|
local Error;
|
||||||
if typeof(resultBody) == typeof({}) and resultBody["message"] then
|
if typeof(resultBody) == typeof({}) and resultBody["message"] then
|
||||||
Error = resultBody["message"]
|
Error = resultBody["message"]
|
||||||
@ -14,30 +15,39 @@ function errorHandler(type: string, resultBody: any, resultObject: {})
|
|||||||
Error = "An Unexpected Error occoured."
|
Error = "An Unexpected Error occoured."
|
||||||
end
|
end
|
||||||
|
|
||||||
if type == "collection" then
|
local statusCode = resultObject["StatusCode"]
|
||||||
if resultObject["StatusCode"] == 401 then
|
if callInformation.type == "collection" then
|
||||||
|
if statusCode == 401 then
|
||||||
Error = AuthorizationError.InvalidAccessToken("InvalidAccessToken")
|
Error = AuthorizationError.InvalidAccessToken("InvalidAccessToken")
|
||||||
elseif resultObject["StatusCode"] == 404 then
|
elseif statusCode == 404 then
|
||||||
Error = CollectionError.CollectionNotFound("CollectionNotFound")
|
Error = CollectionError.CollectionNotFound("CollectionNotFound")
|
||||||
elseif resultObject["StatusCode"] == 400 then
|
elseif statusCode == 400 then
|
||||||
Error = CollectionError.CollectionAlreadyExists("CollectionAlreadyExists")
|
Error = CollectionError.CollectionAlreadyExists("CollectionAlreadyExists")
|
||||||
end
|
end
|
||||||
elseif type == "entry" then
|
elseif callInformation.type == "entry" then
|
||||||
if resultObject["StatusCode"] == 401 then
|
if statusCode == 401 then
|
||||||
Error = AuthorizationError.InvalidAccessToken("InvalidAccessToken")
|
Error = AuthorizationError.InvalidAccessToken("InvalidAccessToken")
|
||||||
elseif resultObject["StatusCode"] == 404 then
|
elseif statusCode == 404 then
|
||||||
Error = CollectionError.CollectionNotFound("CollectionNotFound")
|
Error = CollectionError.CollectionNotFound("CollectionNotFound")
|
||||||
elseif resultObject["StatusCode"] == 400 then
|
elseif statusCode == 400 then
|
||||||
Error = EntryError.InvalidEntryData("InvalidEntryData")
|
Error = EntryError.InvalidEntryData("InvalidEntryData")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if(statusCode ~= 400 and statusCode ~= 401) then
|
||||||
|
if retryCount > 0 then
|
||||||
|
warn("[MarcSync HTTPRequest Handler] MarcSync HTTP Request failed with error: "..Error.." and status code: "..statusCode..". Retrying Request. ("..retryCount..") retries left")
|
||||||
|
task.wait(3)
|
||||||
|
return require(script.Parent.Utils).makeHTTPRequest(callInformation.type, callInformation.method, callInformation.url, callInformation.body, callInformation.authorization, {retryCount = retryCount - 1})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return {["success"] = false, ["errorMessage"] = Error}
|
return {["success"] = false, ["errorMessage"] = Error}
|
||||||
end
|
end
|
||||||
|
|
||||||
local utils = {}
|
local utils = {}
|
||||||
|
|
||||||
function utils.makeHTTPRequest(type: string, method: string, url: string, body: {}, authorization: string):{["success"]: boolean, ["message"]: string}
|
function utils.makeHTTPRequest(type: string, method: string, url: string, body: {}, authorization: string, options: Types.ClientOptions):{["success"]: boolean, ["message"]: string}
|
||||||
local resultObj;
|
local resultObj;
|
||||||
local resultBody;
|
local resultBody;
|
||||||
local success = pcall(function()
|
local success = pcall(function()
|
||||||
@ -54,7 +64,13 @@ function utils.makeHTTPRequest(type: string, method: string, url: string, body:
|
|||||||
if resultBody["warning"] then warn('[MarcSync HTTPRequest Handler] MarcSync HTTP Request returned warning for URL "'..url..'" with body: "'..HttpService:JSONEncode(body)..'": '..resultBody["warning"]) end
|
if resultBody["warning"] then warn('[MarcSync HTTPRequest Handler] MarcSync HTTP Request returned warning for URL "'..url..'" with body: "'..HttpService:JSONEncode(body)..'": '..resultBody["warning"]) end
|
||||||
return resultBody
|
return resultBody
|
||||||
end
|
end
|
||||||
return errorHandler(type, resultBody, resultObj)
|
return errorHandler({
|
||||||
|
type = type,
|
||||||
|
method = method,
|
||||||
|
url = url,
|
||||||
|
body = body,
|
||||||
|
authorization = authorization
|
||||||
|
}, resultBody, resultObj, options.retryCount)
|
||||||
end
|
end
|
||||||
|
|
||||||
return utils
|
return utils
|
@ -18,6 +18,24 @@ METHODS
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## CONSTRUCTOR
|
||||||
|
|
||||||
|
### .new(`accessToken:` [string](https://www.lua.org/pil/2.4.html), `options:` [ClientOptions?](../types/ClientOptions))
|
||||||
|
Creates a new MarcSync client.
|
||||||
|
|
||||||
|
:::info Info
|
||||||
|
When creating a new client, you must provide an `accessToken`. This argument can either be the key of the "tokens" table in the client's Class or the actual token itself. If you provide the key, the client will automatically try to fetch the token from the "tokens" table. If you provide the token itself, the client will use that token instead. If no token is found by the key provided, it will use the key as the token itself.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::info Info
|
||||||
|
The `options` argument is optional and can be used to specify the options of the client. If you do not provide any options, the client will use the default options. The default options are as follows:
|
||||||
|
```lua
|
||||||
|
{
|
||||||
|
retryCount = 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
## METHODS
|
## METHODS
|
||||||
|
|
||||||
### :getVersion(`clientId:` [number?](https://www.lua.org/pil/2.3.html))
|
### :getVersion(`clientId:` [number?](https://www.lua.org/pil/2.3.html))
|
||||||
|
11
website/docs-marcsync-dev/docs/types/ClientOptions.md
Normal file
11
website/docs-marcsync-dev/docs/types/ClientOptions.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# ClientOptions
|
||||||
|
|
||||||
|
ClientOptions is a type which is used to specify the options of a client. It is used in the [MarcSyncClient](../classes/MarcSyncClient) class when creating a new client.
|
||||||
|
|
||||||
|
## Type Definition
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type ClientOptions = {
|
||||||
|
retryCount: number
|
||||||
|
}
|
||||||
|
```
|
Loading…
x
Reference in New Issue
Block a user