Pārlūkot izejas kodu

Temporary fix to Twitter's global timeline error

Zed 4 gadi atpakaļ
vecāks
revīzija
cdb4efadfe
3 mainītis faili ar 31 papildinājumiem un 16 dzēšanām
  1. 12 4
      src/apiutils.nim
  2. 12 10
      src/http_pool.nim
  3. 7 2
      src/routes/timeline.nim

+ 12 - 4
src/apiutils.nim

@@ -58,11 +58,17 @@ template fetchImpl(result, fetchBody) {.dirty.} =
   if token.tok.len == 0:
     raise rateLimitError()
 
+  var
+    client = pool.acquire(genHeaders(token))
+    badClient = false
+
   try:
-    var resp: AsyncResponse
-    result = pool.use(genHeaders(token)):
-      resp = await c.get($url)
-      await resp.body
+    let resp = await client.get($url)
+    result = await resp.body
+
+    if resp.status == $Http503:
+      badClient = true
+      raise newException(InternalError, result)
 
     if result.len > 0:
       if resp.headers.getOrDefault("content-encoding") == "gzip":
@@ -83,6 +89,8 @@ template fetchImpl(result, fetchBody) {.dirty.} =
     if "length" notin e.msg and "descriptor" notin e.msg:
       release(token, invalid=true)
     raise rateLimitError()
+  finally:
+    pool.release(client, badClient=badClient)
 
 proc fetch*(url: Uri; api: Api): Future[JsonNode] {.async.} =
   var body: string

+ 12 - 10
src/http_pool.nim

@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: AGPL-3.0-only
-import asyncdispatch, httpclient
+import httpclient
 
 type
   HttpPool* = ref object
@@ -17,20 +17,22 @@ proc setHttpProxy*(url: string; auth: string) =
   else:
     proxy = nil
 
-proc release*(pool: HttpPool; client: AsyncHttpClient) =
-  if pool.conns.len >= maxConns:
-    client.close()
+proc release*(pool: HttpPool; client: AsyncHttpClient; badClient=false) =
+  if pool.conns.len >= maxConns or badClient:
+    try: client.close()
+    except: discard
   elif client != nil:
     pool.conns.insert(client)
 
-template use*(pool: HttpPool; heads: HttpHeaders; body: untyped): untyped =
-  var c {.inject.}: AsyncHttpClient
-
+proc acquire*(pool: HttpPool; heads: HttpHeaders): AsyncHttpClient =
   if pool.conns.len == 0:
-    c = newAsyncHttpClient(headers=heads, proxy=proxy)
+    result = newAsyncHttpClient(headers=heads, proxy=proxy)
   else:
-    c = pool.conns.pop()
-    c.headers = heads
+    result = pool.conns.pop()
+    result.headers = heads
+
+template use*(pool: HttpPool; heads: HttpHeaders; body: untyped): untyped =
+  let c {.inject.} = pool.acquire(heads)
 
   try:
     body

+ 7 - 2
src/routes/timeline.nim

@@ -45,10 +45,15 @@ proc fetchTimeline*(after: string; query: Query; skipRail=false):
   else:
     rail = getCachedPhotoRail(name)
 
+  # var timeline =
+  #   case query.kind
+  #   of posts: await getTimeline(profileId, after)
+  #   of replies: await getTimeline(profileId, after, replies=true)
+  #   of media: await getMediaTimeline(profileId, after)
+  #   else: await getSearch[Tweet](query, after)
+
   var timeline =
     case query.kind
-    of posts: await getTimeline(profileId, after)
-    of replies: await getTimeline(profileId, after, replies=true)
     of media: await getMediaTimeline(profileId, after)
     else: await getSearch[Tweet](query, after)