Skip to content

Commit

Permalink
feat: add round number to the data model (#58)
Browse files Browse the repository at this point in the history
Add a new column to `retrievals` table:
```
created_at_round BIGINT NOT NULL
```

Add a new column to `retrieval_results` table:
```
completed_at_round BIGINT NOT NULL
```

Rework the HTTP handler and the test suite to fill these new columns,
using a hard-coded round number (for now).

Signed-off-by: Miroslav Bajtoš <[email protected]>
  • Loading branch information
bajtos authored Aug 31, 2023
1 parent b6feb9e commit bbda3fa
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 14 deletions.
7 changes: 6 additions & 1 deletion bin/spark.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ Sentry.init({
tracesSampleRate: 0.1
})

const getCurrentRound = async () => {
// TBD
return 0
}

const client = new pg.Pool({ connectionString: DATABASE_URL })
await client.connect()
client.on('error', err => {
Expand All @@ -39,7 +44,7 @@ client.on('error', err => {
// https://github.com/brianc/node-postgres/issues/1324#issuecomment-308778405
console.error('An idle client has experienced an error', err.stack)
})
const handler = await createHandler({ client, logger: console })
const handler = await createHandler({ client, logger: console, getCurrentRound })
const server = http.createServer(handler)
server.listen(PORT)
await once(server, 'listening')
Expand Down
32 changes: 19 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@ import getRawBody from 'raw-body'
import assert from 'http-assert'
import { validate } from './lib/validate.js'

const handler = async (req, res, client) => {
const handler = async (req, res, client, getCurrentRound) => {
const segs = req.url.split('/').filter(Boolean)
if (segs[0] === 'retrievals' && req.method === 'POST') {
await createRetrieval(req, res, client)
await createRetrieval(req, res, client, getCurrentRound)
} else if (segs[0] === 'retrievals' && req.method === 'PATCH') {
await setRetrievalResult(req, res, client, Number(segs[1]))
await setRetrievalResult(req, res, client, Number(segs[1]), getCurrentRound)
} else if (segs[0] === 'retrievals' && req.method === 'GET') {
await getRetrieval(req, res, client, Number(segs[1]))
} else {
res.end('Hello World!')
}
}

const createRetrieval = async (req, res, client) => {
const createRetrieval = async (req, res, client, getCurrentRound) => {
const round = await getCurrentRound()
const body = await getRawBody(req, { limit: '100kb' })
const meta = body.length > 0 ? JSON.parse(body) : {}
validate(meta, 'sparkVersion', { type: 'string', required: false })
Expand All @@ -36,14 +37,16 @@ const createRetrieval = async (req, res, client) => {
INSERT INTO retrievals (
retrieval_template_id,
spark_version,
zinnia_version
zinnia_version,
created_at_round
)
VALUES ($1, $2, $3)
VALUES ($1, $2, $3, $4)
RETURNING id
`, [
retrievalTemplate.id,
meta.sparkVersion,
meta.zinniaVersion
meta.zinniaVersion,
round
])
json(res, {
id: retrieval.id,
Expand All @@ -53,7 +56,8 @@ const createRetrieval = async (req, res, client) => {
})
}

const setRetrievalResult = async (req, res, client, retrievalId) => {
const setRetrievalResult = async (req, res, client, retrievalId, getCurrentRound) => {
const round = await getCurrentRound()
assert(!Number.isNaN(retrievalId), 400, 'Invalid Retrieval ID')
const body = await getRawBody(req, { limit: '100kb' })
const result = JSON.parse(body)
Expand All @@ -78,10 +82,11 @@ const setRetrievalResult = async (req, res, client, retrievalId) => {
first_byte_at,
end_at,
byte_length,
attestation
attestation,
completed_at_round
)
VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11
)
`, [
retrievalId,
Expand All @@ -93,7 +98,8 @@ const setRetrievalResult = async (req, res, client, retrievalId) => {
new Date(result.firstByteAt),
new Date(result.endAt),
result.byteLength,
result.attestation
result.attestation,
round
])
} catch (err) {
if (err.constraint === 'retrieval_results_retrieval_id_fkey') {
Expand Down Expand Up @@ -169,12 +175,12 @@ const errorHandler = (res, err, logger) => {
}
}

export const createHandler = async ({ client, logger }) => {
export const createHandler = async ({ client, logger, getCurrentRound }) => {
await migrate(client)
return (req, res) => {
const start = new Date()
logger.info(`${req.method} ${req.url} ...`)
handler(req, res, client)
handler(req, res, client, getCurrentRound)
.catch(err => errorHandler(res, err, logger))
.then(() => {
logger.info(`${req.method} ${req.url} ${res.statusCode} (${new Date() - start}ms)`)
Expand Down
9 changes: 9 additions & 0 deletions migrations/012.do.round-number.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- bigint uses 64 bits, the upper limit is +9223372036854775807
-- Postgres and SQL do not support unsigned integers
ALTER TABLE retrievals ADD COLUMN created_at_round BIGINT;
UPDATE retrievals SET created_at_round = 0;
ALTER TABLE retrievals ALTER COLUMN created_at_round SET NOT NULL;

ALTER TABLE retrieval_results ADD COLUMN completed_at_round BIGINT;
UPDATE retrieval_results SET completed_at_round = 0;
ALTER TABLE retrieval_results ALTER COLUMN completed_at_round SET NOT NULL;
13 changes: 13 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ describe('Routes', () => {
logger: {
info () {},
error (...args) { console.error(...args) }
},
async getCurrentRound () {
// TBD
// We return a string because 64bit integers JavaScript `number` cannot
// represent all 64bit values
return '42'
}
})
server = http.createServer(handler)
Expand Down Expand Up @@ -60,6 +66,12 @@ describe('Routes', () => {
assert.strictEqual(typeof body.cid, 'string')
assert.strictEqual(typeof body.providerAddress, 'string')
assert.strictEqual(typeof body.protocol, 'string')

const { rows: [retrievalRow] } = await client.query(
'SELECT * FROM retrievals WHERE id = $1',
[body.id]
)
assert.strictEqual(retrievalRow.created_at_round, '42')
})
it('uses random retrieval templates', async () => {
const makeRequest = async () => {
Expand Down Expand Up @@ -178,6 +190,7 @@ describe('Routes', () => {
)
assert.strictEqual(retrievalResultRow.byte_length, result.byteLength)
assert.strictEqual(retrievalResultRow.attestation, result.attestation)
assert.strictEqual(retrievalResultRow.completed_at_round, '42')
})
it('handles invalid JSON', async () => {
const { id: retrievalId } = await givenRetrieval()
Expand Down

0 comments on commit bbda3fa

Please sign in to comment.