diff --git a/lib/preprocess.js b/lib/preprocess.js index 9a166ed4..36fcffb7 100644 --- a/lib/preprocess.js +++ b/lib/preprocess.js @@ -27,7 +27,7 @@ export class Measurement { this.inet_group = pointerize(m.inet_group) this.finished_at = parseDateTime(m.finished_at) this.provider_address = pointerize(m.provider_address) - this.protocol = pointerize(m.protocol) + this.protocol = pointerize(m.protocol?.toLowerCase()) this.byte_length = m.byte_length this.start_at = parseDateTime(m.start_at) this.first_byte_at = parseDateTime(m.first_byte_at) diff --git a/lib/provider-retrieval-result-stats.js b/lib/provider-retrieval-result-stats.js index 02e00108..69f66ee7 100644 --- a/lib/provider-retrieval-result-stats.js +++ b/lib/provider-retrieval-result-stats.js @@ -16,15 +16,18 @@ const withPgClient = fn => async ({ createPgClient, ...args }) => { } export const build = committees => { - /** @type {Map} */ + /** @type {Map} */ const providerRetrievalResultStats = new Map() for (const c of committees) { // IMPORTANT: include minority results in the calculation for (const m of c.measurements) { const minerId = m.minerId - const retrievalStats = providerRetrievalResultStats.get(minerId) ?? { total: 0, successful: 0 } + const retrievalStats = providerRetrievalResultStats.get(minerId) ?? { total: 0, successful: 0, successfulHttp: 0 } retrievalStats.total++ - if (m.retrievalResult === 'OK') retrievalStats.successful++ + if (m.retrievalResult === 'OK') { + retrievalStats.successful++ + if (m.protocol && m.protocol === 'http') { retrievalStats.successfulHttp++ } + } providerRetrievalResultStats.set(minerId, retrievalStats) } } diff --git a/lib/public-stats.js b/lib/public-stats.js index 40ffdf2c..44bb7dc9 100644 --- a/lib/public-stats.js +++ b/lib/public-stats.js @@ -38,21 +38,24 @@ export const updatePublicStats = async ({ createPgClient, committees, honestMeas * @param {object} stats * @param {number} stats.total * @param {number} stats.successful + * @param {number} stats.successfulHttp */ -const updateRetrievalStats = async (pgClient, minerId, { total, successful }) => { - debug('Updating public retrieval stats for miner %s: total += %s successful += %s', minerId, total, successful) +const updateRetrievalStats = async (pgClient, minerId, { total, successful, successfulHttp }) => { + debug('Updating public retrieval stats for miner %s: total += %s successful += %s, successful_http += %s', minerId, total, successful, successfulHttp) await pgClient.query(` INSERT INTO retrieval_stats - (day, miner_id, total, successful) + (day, miner_id, total, successful, successful_http) VALUES - (now(), $1, $2, $3) + (now(), $1, $2, $3, $4) ON CONFLICT(day, miner_id) DO UPDATE SET total = retrieval_stats.total + $2, - successful = retrieval_stats.successful + $3 + successful = retrieval_stats.successful + $3, + successful_http = retrieval_stats.successful_http + $4 `, [ minerId, total, - successful + successful, + successfulHttp ]) } diff --git a/migrations/021.do.sucessful-http-retrieval-stats.sql b/migrations/021.do.sucessful-http-retrieval-stats.sql new file mode 100644 index 00000000..a95de3e0 --- /dev/null +++ b/migrations/021.do.sucessful-http-retrieval-stats.sql @@ -0,0 +1 @@ +ALTER TABLE retrieval_stats ADD COLUMN IF NOT EXISTS successful_http INT; diff --git a/test/evaluate.js b/test/evaluate.js index 2e01baee..ae7c3d9a 100644 --- a/test/evaluate.js +++ b/test/evaluate.js @@ -96,10 +96,11 @@ describe('evaluate', async function () { day: today(), miner_id: VALID_TASK.minerId, total: 1, - successful: 1 + successful: 1, + // None of the measurements use http + successful_http: 0 }]) }) - it('handles empty rounds', async () => { const round = new RoundData(0n) const setScoresCalls = [] diff --git a/test/provider-retrieval-result-stats.test.js b/test/provider-retrieval-result-stats.test.js index 2ee0a415..35e4fd62 100644 --- a/test/provider-retrieval-result-stats.test.js +++ b/test/provider-retrieval-result-stats.test.js @@ -37,20 +37,24 @@ describe('Provider Retrieval Result Stats', () => { measurements: [ { minerId: '0', - retrievalResult: 'OK' + retrievalResult: 'OK', + protocol: 'http' }, { minerId: '1', - retrievalResult: 'TIMEOUT' + retrievalResult: 'TIMEOUT', + protocol: 'http' } ] }, { measurements: [ { minerId: '0', - retrievalResult: 'OK' + retrievalResult: 'OK', + protocol: 'bitswap' }, { + // Should be able to handle and reject undefined protocol minerId: '1', retrievalResult: 'TIMEOUT' } @@ -58,8 +62,8 @@ describe('Provider Retrieval Result Stats', () => { } ]) assert.deepStrictEqual(stats, new Map([ - ['0', { total: 2, successful: 2 }], - ['1', { total: 2, successful: 0 }] + ['0', { total: 2, successful: 2, successfulHttp: 1 }], + ['1', { total: 2, successful: 0, successfulHttp: 0 }] ])) }) }) @@ -137,22 +141,26 @@ describe('Provider Retrieval Result Stats', () => { measurements: [ { minerId: '0', - retrievalResult: 'OK' + retrievalResult: 'OK', + protocol: 'http' }, { minerId: '1', - retrievalResult: 'TIMEOUT' + retrievalResult: 'TIMEOUT', + protocol: 'http' } ] }, { measurements: [ { minerId: '0', - retrievalResult: 'OK' + retrievalResult: 'OK', + protocol: 'bitswap' }, { minerId: '1', - retrievalResult: 'TIMEOUT' + retrievalResult: 'TIMEOUT', + protocol: 'bitswap' } ] } @@ -168,8 +176,8 @@ describe('Provider Retrieval Result Stats', () => { contract_address: ieContractAddress, measurement_batches: round.measurementBatches, provider_retrieval_result_stats: { - 0: { successful: 2, total: 2 }, - 1: { successful: 0, total: 2 } + 0: { successful: 2, total: 2, successfulHttp: 1 }, + 1: { successful: 0, total: 2, successfulHttp: 0 } }, round_details: 'baguqeerawg5jfpiy2g5xp5d422uwa3mpyzkmiguoeecesds7q65mn2hdoa4q', round_index: String(round.index), diff --git a/test/public-stats.test.js b/test/public-stats.test.js index 2354ab45..d344a69f 100644 --- a/test/public-stats.test.js +++ b/test/public-stats.test.js @@ -87,6 +87,50 @@ describe('public-stats', () => { { day: today, total: 2 + 3, successful: 1 + 1 } ]) }) + it('calculates successful http retrievals correctly', async () => { + /** @type {Measurement[]} */ + const honestMeasurements = [ + { ...VALID_MEASUREMENT, protocol: 'http', retrievalResult: 'OK' }, + { ...VALID_MEASUREMENT, protocol: 'graphsync', retrievalResult: 'OK' }, + { ...VALID_MEASUREMENT, protocol: 'http', retrievalResult: 'HTTP_500' }, + { ...VALID_MEASUREMENT, protocol: 'graphsync', retrievalResult: 'LASSIE_500' } + ] + const allMeasurements = honestMeasurements + let committees = buildEvaluatedCommitteesFromMeasurements(honestMeasurements) + + await updatePublicStats({ + createPgClient, + committees, + honestMeasurements, + allMeasurements, + findDealClients: (_minerId, _cid) => ['f0client'] + }) + + const { rows: created } = await pgClient.query( + 'SELECT day::TEXT, total, successful, successful_http FROM retrieval_stats' + ) + assert.deepStrictEqual(created, [ + { day: today, total: 4, successful: 2, successful_http: 1 } + ]) + + // Let's add another successful http retrieval to make sure the updating process works as expected + honestMeasurements.push({ ...VALID_MEASUREMENT, retrievalResult: 'OK', protocol: 'http' }) + committees = buildEvaluatedCommitteesFromMeasurements(honestMeasurements) + await updatePublicStats({ + createPgClient, + committees, + honestMeasurements, + allMeasurements, + findDealClients: (_minerId, _cid) => ['f0client'] + }) + + const { rows: updated } = await pgClient.query( + 'SELECT day::TEXT, total, successful, successful_http FROM retrieval_stats' + ) + assert.deepStrictEqual(updated, [ + { day: today, total: 4 + 5, successful: 2 + 3, successful_http: 1 + 2 } + ]) + }) it('creates or updates the row for today - multiple miners', async () => { /** @type {Measurement[]} */ @@ -164,10 +208,10 @@ describe('public-stats', () => { }) const { rows: created } = await pgClient.query( - 'SELECT day::TEXT, total, successful FROM retrieval_stats' + 'SELECT day::TEXT, total, successful, successful_http FROM retrieval_stats' ) assert.deepStrictEqual(created, [ - { day: today, total: 3, successful: 2 } + { day: today, total: 3, successful: 2, successful_http: 0 } ]) }) })