Skip to content

Commit

Permalink
Optimize message status updates (#159)
Browse files Browse the repository at this point in the history
* Optimize message status updates
* Remove unused functions

Signed-off-by: Miroslav Kovar <[email protected]>
  • Loading branch information
mirgee authored Apr 11, 2022
1 parent c6a26ff commit 250acf6
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 251 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict';

var dbm;
var type;
var seed;
var fs = require('fs');
var path = require('path');
var Promise;

/**
* We receive the dbmigrate dependency from dbmigrate initially.
* This enables us to not have to rely on NODE_PATH.
*/
exports.setup = function(options, seedLink) {
dbm = options.dbmigrate;
type = dbm.dataType;
seed = seedLink;
Promise = options.Promise;
};

exports.up = function(db) {
var filePath = path.join(__dirname, 'sqls', '20220407134403-unique-uid-constrain-up.sql');
return new Promise( function( resolve, reject ) {
fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){
if (err) return reject(err);
console.log('received data: ' + data);

resolve(data);
});
})
.then(function(data) {
return db.runSql(data);
});
};

exports.down = function(db) {
var filePath = path.join(__dirname, 'sqls', '20220407134403-unique-uid-constrain-down.sql');
return new Promise( function( resolve, reject ) {
fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){
if (err) return reject(err);
console.log('received data: ' + data);

resolve(data);
});
})
.then(function(data) {
return db.runSql(data);
});
};

exports._meta = {
"version": 1
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* Replace with your SQL commands */
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE messages ADD CONSTRAINT unique_uid UNIQUE (uid)
6 changes: 3 additions & 3 deletions vcxagency-client/src/messaging/client2agency/msgs-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ function buildMsgVcxV2UpdateMsgStatusByConns (statusCode, uidsByConns) {
return msg
}

function buildMsgVcxV2MsgStatusUpdatedByConns (failedUidsByConns, updatedUidsByConns) {
function buildMsgVcxV2MsgStatusUpdatedByConns () {
const msg = {
'@type': MSGTYPE_MSG_STATUS_UPDATED_BY_CONNS,
failed: failedUidsByConns, // [{"pairwiseDID":"Fp4eVWcjyRawjNWgnJmJWD","uids":["aBcDeF1234"]}]}
updatedUidsByConns // example: [{"pairwiseDID":"Fp4eVWcjyRawjNWgnJmJWD","uids":["b7vh36XiTe"]}]}
failed: [],
updatedUidsByConns: []
}
return msg
}
Expand Down
51 changes: 13 additions & 38 deletions vcxagency-node/src/service/entities/agent/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,48 +225,23 @@ async function buildAgentAO (entityRecord, serviceWallets, serviceStorage, route
return buildMsgVcxV2MsgsByConns(msgsByConns)
}

async function convertToUidsByPwDids (uidsByAconnDids, ignoreNotFound = false) {
const uidsByPwDids = []
for (const rec of uidsByAconnDids) {
const { agentConnDid, uids } = rec
const userPwDid = await serviceStorage.aconnDidToPwDid(agentDid, agentConnDid)
if (userPwDid) {
uidsByPwDids.push({ pairwiseDID: userPwDid, uids })
} else if (!ignoreNotFound) {
throw Error(`AgentConnectionDid ${agentConnDid} could not be mapped to any userPwDid.`)
// "failed":[],"updatedUidsByConns":[{"pairwiseDID":"Fp4eVWcjyRawjNWgnJmJWD","uids":["b7vh36XiTe"]}]}
async function _handleUpdateMsgsStatusByConns (statusCode, uidsByConns) {
function getUidsFromUidsByConns (uidsByConns) {
const uids = []
for (const uidsByConn of uidsByConns) {
uids.push(...uidsByConn.uids)
}
return uids
}
return uidsByPwDids
}

/**
* Takes list of "uids by pw dids", example: [{"pairwiseDID":"Fp4eVWcjyRawjNWgnJmJWD","uids":["b7vh36XiTe"]}]}
* and converts it to "uids by agent connection dids": [{"agentConnDid":"abcd1234565","uids":["b7vh36XiTe"]}]}
* So that each userPairwiseDid is converted to agentConnectionDid
* @param {array} uidsByPwDids - Message data
* @param {boolean} ignoreNotFound - Message data
*/
async function convertToUidsByAgentConnDids (uidsByPwDids, ignoreNotFound = false) {
const uidsByAconnDids = []
for (const rec of uidsByPwDids) {
const { pairwiseDID, uids } = rec
const agentConnDid = await serviceStorage.pwDidToAconnDid(agentDid, pairwiseDID)
if (agentConnDid) {
uidsByAconnDids.push({ agentConnDid, uids })
} else if (!ignoreNotFound) {
throw Error(`UserPwDid ${pairwiseDID} could not be mapped to agenConnectionDid.`)
}
if (!uidsByConns || !Array.isArray(uidsByConns)) {
logger.warn(`Agent ${agentDid} attempting to update status codes, but uidsByConns ${uidsByConns} is empty or not an array`)
return
}
return uidsByAconnDids
}

// "failed":[],"updatedUidsByConns":[{"pairwiseDID":"Fp4eVWcjyRawjNWgnJmJWD","uids":["b7vh36XiTe"]}]}
async function _handleUpdateMsgsStatusByConns (statusCode, uidsByConns) {
const uidsByAgentConnDids = await convertToUidsByAgentConnDids(uidsByConns, true)
const { failed, updated } = await serviceStorage.updateStatusCodes(agentDid, uidsByAgentConnDids, statusCode)
const updatedUidsByConns = await convertToUidsByPwDids(updated)
const failedUidsByConns = await convertToUidsByPwDids(failed)
return buildMsgVcxV2MsgStatusUpdatedByConns(failedUidsByConns, updatedUidsByConns)
const uids = getUidsFromUidsByConns(uidsByConns)
await serviceStorage.updateStatusCodeAgentConnection(agentDid, uids, statusCode)
return buildMsgVcxV2MsgStatusUpdatedByConns()
}

async function _handleSignUpMsg (_msgObject) {
Expand Down
114 changes: 5 additions & 109 deletions vcxagency-node/src/service/storage/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,54 +188,20 @@ async function createDataStorage (appStorageConfig) {
/**
* Updates statusCodes for messages on particular agent and its particular connection.
* @param {string} agentDid - DID of the agent.
* @param {string} agentConnDid - DID of the agent connection. Must belong to agent.
* @param {array} uids - list of message UIDs for whom new status should be set.
* @param {string} newStatusCode - New status code to be set for matched messages.
*/
async function updateStatusCodeAgentConnection (agentDid, agentConnDid, uids, newStatusCode) {
if (!agentDid || !agentConnDid) {
throw Error('AgentDid or AgentConnDid was not specified.')
async function updateStatusCodeAgentConnection (agentDid, uids, newStatusCode) {
if (!agentDid) {
throw Error(`Failed to update status codes for messages ${uids}: AgentDid was not specified.`)
}
if (uids.length === 0) {
return { failedUids: [], updatedUids: [] }
return
}
// todo: before we run actual update, we should port: see dummy's check_if_message_status_can_be_updated
// see: https://github.com/hyperledger/indy-sdk/blob/d3057f1e21f01768104ca129de63a15d1b5e302e/vcx/dummy-cloud-agent/src/actors/agent_connection.rs
// But Dummy Cloud Agency throws error if a single message in the set cannot be updated which seems like
// a strange behaviour. Rather the uid should rather be just included in failedUids portion of response?
// dummy cloud agency always return empty array for failed uids
const values = [newStatusCode, agentDid, uids]
const query = 'UPDATE messages SET status_code = ? WHERE agent_did = ? AND uid IN(?)'
if (process.env.EXPLAIN_QUERIES === 'true') { explainQuery(query, values) }
await timeOperation(queryDb, { query, values, opName: 'updateStatusCodeAgentConnection' }, query, values)
const updatedUids = uids // difficult to find out which UIDs were successfully updated with mysql,
const failedUids = [] // unless we update one by one. With pgsql doable with RETURNING clause.
return { failedUids, updatedUids }
}

/**
* Updates statusCodes for messages on particular agent across many connections.
* @param {string} agentDid - DID of agent message belongs to
* @param {string} statusCode - New status code to be set for matched messages.
* @param {array} uidsByAgentConnDids - example: [{"aconnDid":"6FRuB95abcmzz1nURoHyWE","uids":["Br4CoNP4TU"]}, ...]
*/
async function updateStatusCodes (agentDid, uidsByAgentConnDids, statusCode) {
const failed = []
const updated = []
for (const uidsByConn of uidsByAgentConnDids) {
const { agentConnDid, uids } = uidsByConn
const {
failedUids,
updatedUids
} = await updateStatusCodeAgentConnection(agentDid, agentConnDid, uids, statusCode)
if (failedUids.length > 0) {
failed.push({ agentConnDid, uids: failedUids })
}
if (updatedUids.length > 0) {
updated.push({ agentConnDid, uids: updatedUids })
}
}
return { failed, updated }
}

// ---- ---- ---- ---- ---- ---- Entity records read/write
Expand Down Expand Up @@ -320,32 +286,6 @@ async function createDataStorage (appStorageConfig) {
)
}

/**
* For Agent's connection, converts "User Pairwise Did" into "Agent Connection Did"
* @param {string} agentDid - DID of an Agent owning connection
* @param {string} pwDid - "User Pairwise DID" associated with the connection
*/
async function pwDidToAconnDid (agentDid, pwDid) {
const res = await aconnLinkPairsByPwDids(agentDid, [pwDid])
if (res.length === 0) {
return undefined
}
return res[0].agentConnDid
}

/**
* For Agent's connection, converts "Agent Connection Did" into "User Pairwise Did"
* @param {string} agentDid - DID of an Agent owning connection
* @param {string} aconnDid - "User Pairwise DID" associated with the connection
*/
async function aconnDidToPwDid (agentDid, aconnDid) {
const res = await aconnLinkPairsByAconnDids(agentDid, [aconnDid])
if (res.length === 0) {
return undefined
}
return res[0].userPwDid
}

/**
* Returns list of tuples ( "Agent Connection Did", "User pairwise Did"), each representing one connection.
* @param {string} agentDid - DID of an Agent owning the connection.
Expand Down Expand Up @@ -382,46 +322,6 @@ async function createDataStorage (appStorageConfig) {
return pairs
}

/**
* Maps updateByConn by pwDid to updateByConn by agentConnDid.
* Example: maps [{"pairwiseDID":"12346543AAAAEFGHRoHyWE","uids":["Br4CoNP4TU"]}] to [{"agentConnDid":"6FRuB95abcmzz1nURoHyWE","uids":["Br4CoNP4TU"]}]
* @param {string} agentDid - DID of an Agent owning connection
* @param {array} uidsByUserPwDids - updateByConn by pwDid
* If one of the agent connection DIDs cannot be mapped into pairwiseDID, the update record will be omitted in response
*/
async function convertIntoStorageRequest (agentDid, uidsByUserPwDids) {
const res = []
for (const uidsByUserPwDid of uidsByUserPwDids) {
const { pairwiseDID, uids } = uidsByUserPwDid
const mapped = await aconnLinkPairsByPwDids(agentDid, [pairwiseDID])
if (mapped.length === 1) {
const { agentConnDid } = mapped[0]
res.push({ agentConnDid, uids })
}
}
return res
}

/**
* Maps updateByConn by agentConnDid to updateByConn by pwDid.
* Example: maps [{"agentConnDid":"6FRuB95abcmzz1nURoHyWE","uids":["Br4CoNP4TU"]}] to [{"pairwiseDID":"12346543AAAAEFGHRoHyWE","uids":["Br4CoNP4TU"]}]
* @param {string} agentDid - DID of an Agent owning connection
* @param {array} uidsByUserAgentConnDids - updateByConn by agent connection DIDs
* If one of the agent connection DIDs cannot be mapped into pairwiseDID, the update record will be omitted in response
*/
async function convertIntoUserUpdateResponse (agentDid, uidsByUserAgentConnDids) {
const res = []
for (const uidsByAgentConnDid of uidsByUserAgentConnDids) {
const { agentConnDid, uids } = uidsByAgentConnDid
const mapped = await aconnLinkPairsByAconnDids(agentDid, [agentConnDid])
if (mapped.length === 1) {
const { userPwDid: pairwiseDID } = mapped[0]
res.push({ pairwiseDID, uids })
}
}
return res
}

function cleanUp () {
pool.end()
}
Expand All @@ -433,7 +333,7 @@ async function createDataStorage (appStorageConfig) {
saveEntityRecord,

// messaging
updateStatusCodes,
updateStatusCodeAgentConnection,
storeMessage,
loadMessages,

Expand All @@ -446,10 +346,6 @@ async function createDataStorage (appStorageConfig) {
linkAgentToItsConnection,
aconnLinkPairsByPwDids,
aconnLinkPairsByAconnDids,
convertIntoStorageRequest,
convertIntoUserUpdateResponse,
pwDidToAconnDid,
aconnDidToPwDid,

setHasNewMessage,
getHasNewMessage,
Expand Down
18 changes: 13 additions & 5 deletions vcxagency-node/test/unit/messaging/aconn-msgs.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ let sendToAgency
let tmpDbData
let tmpDbWallet

let msg1Id
let msg2Id
let msg3Id
let msg4Id

function regenerateUuids () {
msg1Id = uuid.v4()
msg2Id = uuid.v4()
msg3Id = uuid.v4()
msg4Id = uuid.v4()
}

beforeAll(async () => {
try {
jest.setTimeout(1000 * 120)
Expand Down Expand Up @@ -94,6 +106,7 @@ afterAll(async () => {
})

beforeEach(async () => {
regenerateUuids()
{
agencyUserWalletKey = await indyGenerateWalletKey()
agencyUserWalletName = `unit-test-${uuid.v4()}`
Expand Down Expand Up @@ -132,11 +145,6 @@ let aconnDid
let aconnVerkey
let aconnUserPwVkey

const msg1Id = uuid.v4()
const msg2Id = uuid.v4()
const msg3Id = uuid.v4()
const msg4Id = uuid.v4()

let agent1Did
let agent1Verkey

Expand Down
Loading

0 comments on commit 250acf6

Please sign in to comment.