Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Use SQL Index to compute reputation score #122

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/modules/orbitdb/indexes/abstract.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ class ChluAbstractIndex {
return await this._getReviewsWrittenByDID(didId)
}

async getReputationScore(didId) {
return await this._getReputationScore(didId)
}

async _getReviewsAboutDID() {
notImplemented();
}
Expand All @@ -172,6 +176,10 @@ class ChluAbstractIndex {
notImplemented();
}

async _getReputationScore() {
notImplemented()
}

}

function notImplemented() {
Expand Down
5 changes: 5 additions & 0 deletions src/modules/orbitdb/indexes/inmemory.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ class ChluInMemoryIndex extends ChluAbstractIndex {
.map(multihash => ({ multihash }))
}

_getReputationScore() {
// The InMemory Index cannot do this.
return null
}

}

function slice(array, offset, limit) {
Expand Down
29 changes: 29 additions & 0 deletions src/modules/orbitdb/indexes/sql.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,35 @@ class ChluSQLIndex extends ChluAbstractIndex {
return formatReviewRecords(list)
}

async _getReputationScore(didId) {
const result = await this.ReviewRecord.findAll({
attributes: [
[this.sequelize.fn('AVERAGE', this.sequelize.col('data.rating_details.value')), 'rating_average'],
[this.sequelize.fn('COUNT'), 'rating_count'],
],
where: {
// Only take out reviews about the didId
[Sequelize.Op.or]: [
{ 'data.popr.vendor_did': didId },
{ 'data.subject.did': didId },
],
// that also have a rating between 1 and 5 included
'data.rating_details.min': 1,
'data.rating_details.max': 5,
'data.rating_details.value': {
[Sequelize.Op.gte]: 1,
[Sequelize.Op.lte]: 5
},
// don't consider records not about the latest version of a review
'latestVersionData': null
}
})
return {
rating_average: get(result[0], 'rating_average', null),
rating_count: get(result[0], 'rating_count', 0),
}
}

}

function formatReviewRecords(list) {
Expand Down
36 changes: 33 additions & 3 deletions tests/OrbitDB.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const ChluInMemoryIndex = require('../src/modules/orbitdb/indexes/inmemory');
const ChluAbstractIndex = require('../src/modules/orbitdb/indexes/abstract');
const { genMultihash } = require('./utils/ipfs');
const { getFakeReviewRecord, makeResolved } = require('./utils/protobuf');
const { cloneDeep } = require('lodash')

async function applyOperation(idx, op) {
return await idx.updateIndex({
Expand Down Expand Up @@ -40,7 +41,7 @@ describe('OrbitDB Module', () => {
directory
});
chluIpfs.reviewRecords.readReviewRecord = sinon.stub()
.callsFake(async multihash => Object.assign({ multihash }, makeResolved(await getFakeReviewRecord()), reviewOverride || {}))
.callsFake(async multihash => Object.assign({ multihash }, cloneDeep(makeResolved(await getFakeReviewRecord()), reviewOverride || {})))
chluIpfs.didIpfsHelper.readPublicDIDDocument = sinon.stub()
.callsFake(async () => Object.assign({
id: 'did:chlu:random'
Expand Down Expand Up @@ -207,12 +208,10 @@ describe('OrbitDB Module', () => {
reviewOverride = { popr: { vendor_did: didId } }
await applyOperation(idx, {
op: ChluInMemoryIndex.operations.ADD_REVIEW_RECORD,
didId, // Retrocompatibility
multihash: genMultihash(1)
})
await applyOperation(idx, {
op: ChluInMemoryIndex.operations.ADD_REVIEW_RECORD,
subjectDidId: didId,
multihash: genMultihash(2)
})
expect((await idx.getReviewsAboutDID(didId)).map(x => x.multihash)).to.deep.equal([
Expand All @@ -222,6 +221,37 @@ describe('OrbitDB Module', () => {
expect(await idx.getReviewsWrittenByDID(didId)).to.deep.equal([])
})

function getRating(x) { return { min: 1, max: 5, value: x } }
const skipForInMemory = item.name === 'InMemory' ? it.skip : it.only

skipForInMemory('computes reputation score about subject DID', async () => {
const didId = 'did:chlu:abc'
reviewOverride = { popr: { vendor_did: didId }, rating_details: getRating(1) }
await applyOperation(idx, {
op: ChluInMemoryIndex.operations.ADD_REVIEW_RECORD,
subjectDidId: didId,
multihash: genMultihash(1)
})
reviewOverride = { popr: { vendor_did: didId }, rating_details: getRating(1) }
await applyOperation(idx, {
op: ChluInMemoryIndex.operations.ADD_REVIEW_RECORD,
subjectDidId: didId,
multihash: genMultihash(2)
})
reviewOverride = { subject: { did: didId }, previous_version_multihash: genMultihash(2), history: [
{ multihash: genMultihash(2) }
], rating_details: getRating(5) }
await applyOperation(idx, {
op: ChluInMemoryIndex.operations.ADD_REVIEW_RECORD,
subjectDidId: didId,
multihash: genMultihash(3)
})
expect(await idx.getReputationScore(didId)).to.deep.equal({
average_score: 3,
count: 2
})
})

it('returns reviews written by author DID', async () => {
const didId = 'did:chlu:abc'
reviewOverride = { customer_signature: { creator: didId } }
Expand Down