KOSync: Set sane socket timeouts properly (#10835)

An attempt was made in the original code, but the whole thing was designed in the hope of actually switching to turbo, so it was super janky without it.
Anyway, we now actually have a sane way to set socket timeouts, so, use that, and set them very tight for now.

This is fairly critical right now, because the server is down, and the default timeouts are ~30s. That happens to be *above* the debounce threshold, so you can't even hope for that to help you. Meaning, right now, you get a 2 * 30s block on resume with auto sync. That's... Very Not Good(TM).

That becomes a single 2s one after this.
reviewable/pr10841/r1
NiLuJe 9 months ago committed by GitHub
parent 21de1a832e
commit 6fa8e1d2fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -51,7 +51,7 @@ function socketutil:set_timeout(block_timeout, total_timeout)
-- Also update the actual LuaSocket & LuaSec constants, because: -- Also update the actual LuaSocket & LuaSec constants, because:
-- 1. LuaSocket's `open` does a `settimeout` *after* create with this constant -- 1. LuaSocket's `open` does a `settimeout` *after* create with this constant
-- 2. KOSync updates it to a stupidly low value -- 2. Rogue code might be attempting to enforce them
http.TIMEOUT = self.block_timeout http.TIMEOUT = self.block_timeout
https.TIMEOUT = self.block_timeout https.TIMEOUT = self.block_timeout
end end

@ -1,5 +1,11 @@
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local DEBUG = require("dbg") local logger = require("logger")
local socketutil = require("socketutil")
-- Push/Pull
local PROGRESS_TIMEOUTS = { 2, 5 }
-- Login/Register
local AUTH_TIMEOUTS = { 5, 10 }
local KOSyncClient = { local KOSyncClient = {
service_spec = nil, service_spec = nil,
@ -15,22 +21,21 @@ function KOSyncClient:new(o)
end end
function KOSyncClient:init() function KOSyncClient:init()
require("socket.http").TIMEOUT = 1
local Spore = require("Spore") local Spore = require("Spore")
self.client = Spore.new_from_spec(self.service_spec, { self.client = Spore.new_from_spec(self.service_spec, {
base_url = self.custom_url, base_url = self.custom_url,
}) })
package.loaded['Spore.Middleware.GinClient'] = {} package.loaded["Spore.Middleware.GinClient"] = {}
require('Spore.Middleware.GinClient').call = function(_, req) require("Spore.Middleware.GinClient").call = function(_, req)
req.headers['accept'] = "application/vnd.koreader.v1+json" req.headers["accept"] = "application/vnd.koreader.v1+json"
end end
package.loaded['Spore.Middleware.KOSyncAuth'] = {} package.loaded["Spore.Middleware.KOSyncAuth"] = {}
require('Spore.Middleware.KOSyncAuth').call = function(args, req) require("Spore.Middleware.KOSyncAuth").call = function(args, req)
req.headers['x-auth-user'] = args.username req.headers["x-auth-user"] = args.username
req.headers['x-auth-key'] = args.userkey req.headers["x-auth-key"] = args.userkey
end end
package.loaded['Spore.Middleware.AsyncHTTP'] = {} package.loaded["Spore.Middleware.AsyncHTTP"] = {}
require('Spore.Middleware.AsyncHTTP').call = function(args, req) require("Spore.Middleware.AsyncHTTP").call = function(args, req)
-- disable async http if Turbo looper is missing -- disable async http if Turbo looper is missing
if not UIManager.looper then return end if not UIManager.looper then return end
req:finalize() req:finalize()
@ -41,7 +46,7 @@ function KOSyncClient:init()
body = req.env.spore.payload, body = req.env.spore.payload,
on_headers = function(headers) on_headers = function(headers)
for header, value in pairs(req.headers) do for header, value in pairs(req.headers) do
if type(header) == 'string' then if type(header) == "string" then
headers:add(header, value) headers:add(header, value)
end end
end end
@ -59,37 +64,41 @@ end
function KOSyncClient:register(username, password) function KOSyncClient:register(username, password)
self.client:reset_middlewares() self.client:reset_middlewares()
self.client:enable('Format.JSON') self.client:enable("Format.JSON")
self.client:enable("GinClient") self.client:enable("GinClient")
socketutil:set_timeout(AUTH_TIMEOUTS[1], AUTH_TIMEOUTS[2])
local ok, res = pcall(function() local ok, res = pcall(function()
return self.client:register({ return self.client:register({
username = username, username = username,
password = password, password = password,
}) })
end) end)
socketutil:reset_timeout()
if ok then if ok then
return res.status == 201, res.body return res.status == 201, res.body
else else
DEBUG(ok, res) logger.dbg("KOSyncClient:register failure:", res)
return false, res.body return false, res.body
end end
end end
function KOSyncClient:authorize(username, password) function KOSyncClient:authorize(username, password)
self.client:reset_middlewares() self.client:reset_middlewares()
self.client:enable('Format.JSON') self.client:enable("Format.JSON")
self.client:enable("GinClient") self.client:enable("GinClient")
self.client:enable("KOSyncAuth", { self.client:enable("KOSyncAuth", {
username = username, username = username,
userkey = password, userkey = password,
}) })
socketutil:set_timeout(AUTH_TIMEOUTS[1], AUTH_TIMEOUTS[2])
local ok, res = pcall(function() local ok, res = pcall(function()
return self.client:authorize() return self.client:authorize()
end) end)
socketutil:reset_timeout()
if ok then if ok then
return res.status == 200, res.body return res.status == 200, res.body
else else
DEBUG("err:", res) logger.dbg("KOSyncClient:authorize failure:", res)
return false, res.body return false, res.body
end end
end end
@ -104,12 +113,14 @@ function KOSyncClient:update_progress(
device_id, device_id,
callback) callback)
self.client:reset_middlewares() self.client:reset_middlewares()
self.client:enable('Format.JSON') self.client:enable("Format.JSON")
self.client:enable("GinClient") self.client:enable("GinClient")
self.client:enable("KOSyncAuth", { self.client:enable("KOSyncAuth", {
username = username, username = username,
userkey = password, userkey = password,
}) })
-- Set *very* tight timeouts to avoid blocking for too long...
socketutil:set_timeout(PROGRESS_TIMEOUTS[1], PROGRESS_TIMEOUTS[2])
local co = coroutine.create(function() local co = coroutine.create(function()
local ok, res = pcall(function() local ok, res = pcall(function()
return self.client:update_progress({ return self.client:update_progress({
@ -123,13 +134,14 @@ function KOSyncClient:update_progress(
if ok then if ok then
callback(res.status == 200, res.body) callback(res.status == 200, res.body)
else else
DEBUG("err:", res) logger.dbg("KOSyncClient:update_progress failure:", res)
callback(false, res.body) callback(false, res.body)
end end
end) end)
self.client:enable("AsyncHTTP", {thread = co}) self.client:enable("AsyncHTTP", {thread = co})
coroutine.resume(co) coroutine.resume(co)
if UIManager.looper then UIManager:setInputTimeout() end if UIManager.looper then UIManager:setInputTimeout() end
socketutil:reset_timeout()
end end
function KOSyncClient:get_progress( function KOSyncClient:get_progress(
@ -138,12 +150,13 @@ function KOSyncClient:get_progress(
document, document,
callback) callback)
self.client:reset_middlewares() self.client:reset_middlewares()
self.client:enable('Format.JSON') self.client:enable("Format.JSON")
self.client:enable("GinClient") self.client:enable("GinClient")
self.client:enable("KOSyncAuth", { self.client:enable("KOSyncAuth", {
username = username, username = username,
userkey = password, userkey = password,
}) })
socketutil:set_timeout(PROGRESS_TIMEOUTS[1], PROGRESS_TIMEOUTS[2])
local co = coroutine.create(function() local co = coroutine.create(function()
local ok, res = pcall(function() local ok, res = pcall(function()
return self.client:get_progress({ return self.client:get_progress({
@ -153,13 +166,14 @@ function KOSyncClient:get_progress(
if ok then if ok then
callback(res.status == 200, res.body) callback(res.status == 200, res.body)
else else
DEBUG("err:", res) logger.dbg("KOSyncClient:get_progress failure:", res)
callback(false, res.body) callback(false, res.body)
end end
end) end)
self.client:enable("AsyncHTTP", {thread = co}) self.client:enable("AsyncHTTP", {thread = co})
coroutine.resume(co) coroutine.resume(co)
if UIManager.looper then UIManager:setInputTimeout() end if UIManager.looper then UIManager:setInputTimeout() end
socketutil:reset_timeout()
end end
return KOSyncClient return KOSyncClient

Loading…
Cancel
Save