From bf9426ede7438add491cdf9ae8f81e439a83d142 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 3 Aug 2020 18:12:46 -0400 Subject: [PATCH] new mechanisms for fetching the feed --- src/routes.js | 65 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/src/routes.js b/src/routes.js index a6f5cd75..56aeda18 100644 --- a/src/routes.js +++ b/src/routes.js @@ -13,6 +13,8 @@ const Common = require('shock-common') const isARealUsableNumber = require('lodash/isFinite') const Big = require('big.js') const size = require('lodash/size') +const { range } = require('ramda') +const flattenDeep = require('lodash/flattenDeep') const getListPage = require('../utils/paginate') const auth = require('../services/auth/auth') @@ -2047,22 +2049,59 @@ module.exports = async ( const { page: pageStr } = req.query const page = Number(pageStr) - if (!isARealUsableNumber(page)) { - return res.status(400).json({ - field: 'page', - errorMessage: 'page must be a number' + const MAX_PAGES_TO_FETCH_FOR_TRY_UNTIL = 4 + /** + * Similar to a "before" query param in cursor based pagination. We call + * it "try" because it is likely that this item lies beyond + * MAX_PAGES_TO_FETCH_FOR_TRY_UNTIL in which case we gracefully just send + * 2 pages and 205 response. + */ + const try_until = req.query + + if (pageStr) { + const page = Number(pageStr) + + if (!isARealUsableNumber(page)) { + return res.status(400).json({ + field: 'page', + errorMessage: 'page must be a number' + }) + } + + if (page < 1) { + return res.status(400).json({ + field: page, + errorMessage: 'page must be a positive number' + }) + } + + return res.status(200).json({ + posts: await GunGetters.getFeedPage(page) + }) + } else if (try_until) { + const promises = range(1, MAX_PAGES_TO_FETCH_FOR_TRY_UNTIL).map(p => + GunGetters.getFeedPage(p) + ) + + let results = await Promise.all(promises) + + const idxIfFound = results.findIndex(pp => + pp.some(p => p.id === try_until) + ) + + if (idxIfFound > -1) { + results = results.slice(0, idxIfFound) + } + + const posts = flattenDeep(results) + + return res.status(200).json({ + posts }) } - if (page < 1) { - return res.status(400).json({ - field: page, - errorMessage: 'page must be a positive number' - }) - } - - return res.status(200).json({ - posts: await GunGetters.getFeedPage(page) + return res.status(400).json({ + errorMessage: `Must provide at least a page or a try_until query param.` }) } catch (err) { return res.status(500).json({