Commit d951ded3 authored by WorldTeacher's avatar WorldTeacher
Browse files

feat(api): add batch session upload endpoint with intelligent batching

- Add submitSessionBatch() to APIClient for batch uploads (up to 100 sessions)
- Add BATCH_UPLOAD_SIZE constant (100) for easy configuration
- Add _groupSessionsByBook() helper to organize sessions by book_id
- Add _submitSingleSession() helper to extract single upload logic
- Add _uploadSessionsWithBatching() with smart upload strategy:
  * Single session: individual upload for immediate feedback
  * 2-100 sessions: single batch upload
  * 100+ sessions: split into chunks of 100
  * Auto-fallback to individual upload if batch endpoint returns 404

Endpoint: POST /api/v1/reading-sessions/batch
Payload: {bookId, bookType, sessions: [{startTime, endTime, ...}]}
Response: Simple success message on 200, error details on failure

Performance improvement: 50 sessions in 1 request (~2-5s) vs 50 requests (~50-100s)

All-or-nothing semantics: entire batch succeeds or fails together.
Handles 404 gracefully by falling back to individual uploads to distinguish
between missing batch endpoint vs missing book on server.
parent f754bd71
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -391,6 +391,57 @@ function APIClient:submitSession(session_data)
    end
end

--[[--
Submit batch of reading sessions for a single book

Submits multiple sessions in a single request for improved performance.
Automatically falls back to individual uploads if batch endpoint is not available (404).

@param book_id Booklore book ID (number)
@param book_type Book type (string): "EPUB", "PDF", etc.
@param sessions Array of session objects (table), max 100 sessions recommended
@return boolean success
@return string message (success or error message)
@return number|nil code HTTP status code
--]]
function APIClient:submitSessionBatch(book_id, book_type, sessions)
    -- Validation
    if not book_id or type(book_id) ~= "number" then
        self:logErr("BookloreSync API: Invalid book_id for batch upload:", book_id)
        return false, "Invalid book_id", nil
    end
    
    if not sessions or type(sessions) ~= "table" or #sessions == 0 then
        self:logErr("BookloreSync API: Invalid or empty sessions array for batch upload")
        return false, "Invalid or empty sessions array", nil
    end
    
    -- Log batch submission
    self:logInfo("BookloreSync API: Submitting batch of", #sessions, "sessions for book:", book_id)
    
    -- Build payload
    local payload = {
        bookId = book_id,
        bookType = book_type or "EPUB",
        sessions = sessions
    }
    
    -- Submit batch
    local success, code, response = self:request("POST", "/api/v1/reading-sessions/batch", payload)
    
    if success then
        self:logInfo("BookloreSync API: Batch submitted successfully -", #sessions, "sessions")
        return true, "Batch synced successfully", code
    else
        local error_msg = response or "Failed to submit batch"
        if code then
            error_msg = "HTTP " .. tostring(code) .. ": " .. error_msg
        end
        self:logWarn("BookloreSync API: Batch submission failed:", error_msg)
        return false, error_msg, code
    end
end

--[[--
Check server health/connectivity

+294 −127

File changed.

Preview size limit exceeded, changes collapsed.