Skip to content

Commit

Permalink
Merge gmod client part with the main client file
Browse files Browse the repository at this point in the history
  • Loading branch information
AMD-NICK committed Dec 22, 2024
1 parent cced971 commit 4cf8990
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 84 deletions.
65 changes: 0 additions & 65 deletions examples/garrysmod-client.lua

This file was deleted.

87 changes: 68 additions & 19 deletions lua/long-polling/client.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
-- source: https://github.com/TRIGONIM/lua-long-polling/blob/e28fff8141c7d1a22e030c9d6132ef853032da84/lua/long-polling/client.lua
-- local kupol = require("long-polling.client")
-- local client = kupol.new("https://lp.example.com/channel")
-- local Client = kupol.new("https://lp.example.com/channel")
-- By default, client use copas and lua-cjson, but you can use your own functions
-- See how to use it in Garry's Mod (without copas and cjson) in examples/
-- from Garry's Mod for example

local kupol = {}

Expand All @@ -21,8 +22,8 @@ function MT:publish(tData)
return code == 201 or res == "OK", code
end

function MT:get(last_id, timeout)
local paramstr = "?ts=" .. (last_id or "") .. "&sleep=" .. (timeout or "")
function MT:get(offset, timeout)
local paramstr = "?ts=" .. (offset or "") .. "&sleep=" .. (timeout or "")

local body, code_or_err = kupol.http_get(self.url .. paramstr)
if not body then return false, code_or_err end
Expand All @@ -40,23 +41,30 @@ function MT:handle_error(err)
self:log("🆘 Error\n\t%s", err)
end

function MT:subscribe(fHandler, last_id, timeout)
kupol.thread_new(function() while true do
local to = last_id and timeout or 0 -- it's better if first request will be fast if last_id not provided
local tData, body = self:get(last_id, to)
function MT:subscribe(fHandler, requested_ts, timeout)
self.thread = kupol.thread_new(function() repeat
local tmt = requested_ts and timeout or 0 -- it's better if first request will be fast if requested_ts not provided
local tData, body = self:get(requested_ts, tmt)
if tData then
if (last_id or 0) > tData.ts then
self:log("🚧 ts on server is less than requested (%d < %d)", tData.ts, last_id)
end
local ts_diff = tData.ts - (requested_ts or 0)

local REM = (requested_ts or 0) > tData.ts -- REMOTE FUCKUP. e.g. remote ts 0, local ts 1000
local LOC = ts_diff > #tData.updates -- LOCAL FUCKUP. e.g. remote ts 100, local ts 0, but 30 updates instead of 100
if REM or LOC then
if REM then
self:log("🚧 ts on server is less than requested (%d < %d)", tData.ts, requested_ts)
end

if LOC then
self:log("🚧 updates lost: %d (got %d, expected %d)", ts_diff - #tData.updates, #tData.updates, ts_diff) -- too long time haven't requested them
end

local updates_should_be = tData.ts - (last_id or 0)
if updates_should_be > #tData.updates then
local updates_lost = updates_should_be - #tData.updates
self:log("🚧 updates lost: %d (got %d, expected %d)", updates_lost, #tData.updates, updates_should_be) -- too long haven't requested them
requested_ts = tData.ts -- emerg reset
else
requested_ts = requested_ts and (requested_ts + #tData.updates) or tData.ts
-- requested_ts = tData.ts
end

-- last_id = last_id and (last_id + #tData.updates) or tData.ts
last_id = tData.ts
for _, update in ipairs(tData.updates) do
local pcallok, res = pcall(fHandler, update, tData.ts)
if not pcallok then
Expand All @@ -67,9 +75,11 @@ function MT:subscribe(fHandler, last_id, timeout)
self:handle_error(body)
kupol.thread_pause(10)
end
end end) -- while true, thread
until (not self.thread) end)
end

local IS_GARRYSMOD = (GM or GAMEMODE) and RunString and hook

local copas_ok, copas = pcall(require, "copas") -- should be loaded before http_v2
if copas_ok then
local http = require("http_v2") -- https://github.com/TRIGONIM/lua-requests-async/blob/main/lua/http_v2.lua
Expand All @@ -87,15 +97,54 @@ if copas_ok then

kupol.thread_new = copas.addthread
kupol.thread_pause = copas.sleep

elseif IS_GARRYSMOD then
function kupol.thread_new(f, ...)
local co = coroutine.create(f)
local function cont(...)
local ok, callback = coroutine.resume(co, ...)
if not ok then error( debug.traceback(co, callback) ) end
if coroutine.status(co) ~= "dead" then callback(cont) end
end
cont(...)
return co
end

function kupol.thread_pause(seconds)
coroutine.yield(function(cont) timer.Simple(seconds, cont) end)
end

function kupol.http_get(url)
return coroutine.yield(function(cont)
http.Fetch(url, function(body, _, _, code) cont(body, code) end,
function(err) cont(false, err) end)
end)
end

function kupol.http_post(url, data)
return coroutine.yield(function(cont)
local ok = HTTP({ url = url, method = "POST",
body = data, type = "application/json",
success = function(code, body) cont(body, code) end,
failed = function(err) cont(false, err) end
})
if not ok then cont(false, "HTTP() failed") end
end)
end

else
-- e.g. in Garry's Mod
print("Kupol: looks like copas is not installed. So you should provide own kupol.http_* and kupol.thread_* functions")
end

local cjson_ok, cjson = pcall(require, "cjson.safe")
if cjson_ok then
kupol.json_encode = cjson.encode
kupol.json_decode = cjson.decode

elseif IS_GARRYSMOD then
kupol.json_encode = util.TableToJSON
kupol.json_decode = util.JSONToTable

else
print("Kupol: looks like lua-cjson is not installed. So you should provide own kupol.json_encode and kupol.json_decode functions")
end
Expand Down

0 comments on commit 4cf8990

Please sign in to comment.