Skip to content

Commit

Permalink
feat: fallback from flat file origins
Browse files Browse the repository at this point in the history
  • Loading branch information
AmeanAsad committed Oct 31, 2023
1 parent 4e1703a commit baf1a62
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 8 deletions.
14 changes: 10 additions & 4 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,10 @@ export class Saturn {
throw new Error(`All attempts to fetch content have failed. Last error: ${lastError.message}`)
}

const fetchContent = async function * () {
const fetchContent = async function * (options) {
let byteCount = 0
const byteChunks = await this.fetchContent(cidPath, opts)
const fetchOptions = Object.assign(opts, options)
const byteChunks = await this.fetchContent(cidPath, fetchOptions)
for await (const chunk of byteChunks) {
// avoid sending duplicate chunks
if (byteCount < byteCountCheckpoint) {
Expand Down Expand Up @@ -327,7 +328,7 @@ export class Saturn {
if (originUrl) {
opts.nodes = Array({ url: originUrl })
try {
yield * fetchContent()
yield * fetchContent({ flatFile: true })
return
} catch (err) {
lastError = err
Expand All @@ -343,6 +344,7 @@ export class Saturn {
* @param {object} [opts={}]
* @param {('car'|'raw')} [opts.format]
* @param {boolean} [opts.raceNodes]
* @param {boolean} [opts.flatFile]
* @param {number} [opts.connectTimeout=5000]
* @param {number} [opts.downloadTimeout=0]
* @returns {Promise<AsyncIterable<Uint8Array>>}
Expand All @@ -367,7 +369,11 @@ export class Saturn {

try {
const itr = metricsIterable(asAsyncIterable(res.body))
yield * extractVerifiedContent(cidPath, itr)
if (opts.flatFile) {
yield * itr
} else {
yield * extractVerifiedContent(cidPath, itr)
}
} catch (err) {
log.error = err.message
controller.abort()
Expand Down
9 changes: 5 additions & 4 deletions test/fallback.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import assert from 'node:assert/strict'
import { describe, mock, test } from 'node:test'

import { Saturn } from '#src/index.js'
import { concatChunks, generateNodes, getMockServer, HTTP_STATUS_GONE, HTTP_STATUS_TIMEOUT, mockJWT, mockNodesHandlers, mockOrchHandler, mockOriginHandler, MSW_SERVER_OPTS } from './test-utils.js'
import { concatChunks, generateNodes, getMockServer, HTTP_STATUS_GONE, HTTP_STATUS_TIMEOUT, mockFlatFileOriginHandler, mockJWT, mockNodesHandlers, mockOrchHandler, mockOriginHandler, MSW_SERVER_OPTS } from './test-utils.js'

const TEST_DEFAULT_ORCH = 'https://orchestrator.strn.pl.test/nodes'
const TEST_NODES_LIST_KEY = 'saturn-nodes'
Expand Down Expand Up @@ -280,7 +280,7 @@ describe('Client Fallback', () => {
mockOrchHandler(numNodes, TEST_DEFAULT_ORCH, TEST_ORIGIN_DOMAIN),
mockJWT(TEST_AUTH),
mockOriginHandler(TEST_ORIGIN_DOMAIN, 0, true),
mockOriginHandler(TEST_CUSTOMER_ORIGIN, 0, false),
mockFlatFileOriginHandler(TEST_CUSTOMER_ORIGIN, 0, false),
...mockNodesHandlers(numNodes, TEST_ORIGIN_DOMAIN, numNodes, HTTP_STATUS_TIMEOUT)
]

Expand All @@ -303,9 +303,10 @@ describe('Client Fallback', () => {

const buffer = await concatChunks(cid)
const actualContent = String.fromCharCode(...buffer)
const expectedContent = 'hello world\n'
const jsonContent = JSON.parse(actualContent)
const expectedContent = JSON.parse('{ "hello": "world" }')

assert.strictEqual(actualContent, expectedContent)
assert.deepEqual(jsonContent, expectedContent)
mock.reset()
server.close()
})
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/hello.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"hello": "world"
}
25 changes: 25 additions & 0 deletions test/test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,31 @@ export function mockOriginHandler (originUrl, delay = 0, error = false) {
})
}

/**
* Generates a mock handler to mimick an origin that serves flat files.
*
* @param {string} originUrl - originUrl
* @param {number} delay - request delay in ms
* @param {boolean} error
* @returns {RestHandler<any>}
*/
export function mockFlatFileOriginHandler (originUrl, delay = 0, error = false) {
originUrl = addHttpPrefix(originUrl)
originUrl = `${originUrl}/ipfs/:cid`
return rest.get(originUrl, (req, res, ctx) => {
if (error) {
throw Error('Simulated Error')
}
const filepath = getFixturePath('hello.json')
const fileContents = fs.readFileSync(filepath)
return res(
ctx.delay(delay),
ctx.status(HTTP_STATUS_OK),
ctx.body(fileContents)
)
})
}

/**
* Generates a mock handler to mimick Saturn's orchestrator /nodes endpoint.
*
Expand Down

0 comments on commit baf1a62

Please sign in to comment.