chore: rename onion requests not having retries

pull/2963/head
Audric Ackermann 1 year ago
parent 665f6df57e
commit a83e44e183

@ -39,7 +39,7 @@ const forceNetworkDeletion = async (): Promise<Array<string> | null> => {
namespace,
});
const ret = await BatchRequests.doSnodeBatchRequest(
const ret = await BatchRequests.doSnodeBatchRequestNoRetries(
[{ method, params: { ...signOpts, namespace, pubkey: usPk } }],
snodeToMakeRequestTo,
10000,
@ -200,7 +200,7 @@ const networkDeleteMessages = async (hashes: Array<string>): Promise<Array<strin
pubkey: userX25519PublicKey,
});
const ret = await BatchRequests.doSnodeBatchRequest(
const ret = await BatchRequests.doSnodeBatchRequestNoRetries(
[{ method, params: signOpts }],
snodeToMakeRequestTo,
10000,

@ -20,20 +20,25 @@ function logSubRequests(requests: Array<BuiltSnodeSubRequests>) {
* This is the equivalent to the batch send on sogs. The target node runs each sub request and returns a list of all the sub status and bodies.
* If the global status code is not 200, an exception is thrown.
* The body is already parsed from json and is enforced to be an Array of at least one element
* Note: This function does not retry by itself.
*
* @param subRequests the list of requests to do
* @param targetNode the node to do the request to, once all the onion routing is done
* @param timeout the timeout at which we should cancel this request.
* @param associatedWith used mostly for handling 421 errors, we need the pubkey the change is associated to
* @param method can be either batch or sequence. A batch call will run all calls even if one of them fails. A sequence call will stop as soon as the first one fails
*/
async function doSnodeBatchRequest(
async function doSnodeBatchRequestNoRetries(
subRequests: Array<BuiltSnodeSubRequests>,
targetNode: Snode,
timeout: number,
associatedWith: string | null,
method: MethodBatchType = 'batch'
): Promise<NotEmptyArrayOfBatchResults> {
window.log.debug(`doSnodeBatchRequest "${method}":`, JSON.stringify(logSubRequests(subRequests)));
window.log.debug(
`doSnodeBatchRequestNoRetries "${method}":`,
JSON.stringify(logSubRequests(subRequests))
);
if (subRequests.length > MAX_SUBREQUESTS_COUNT) {
window.log.error(
@ -43,7 +48,7 @@ async function doSnodeBatchRequest(
`batch subRequests count cannot be more than ${MAX_SUBREQUESTS_COUNT}. Got ${subRequests.length}`
);
}
const result = await SessionRpc.snodeRpc({
const result = await SessionRpc.snodeRpcNoRetries({
method,
params: { requests: subRequests },
targetNode,
@ -52,10 +57,10 @@ async function doSnodeBatchRequest(
});
if (!result) {
window?.log?.warn(
`doSnodeBatchRequest - sessionRpc could not talk to ${targetNode.ip}:${targetNode.port}`
`doSnodeBatchRequestNoRetries - sessionRpc could not talk to ${targetNode.ip}:${targetNode.port}`
);
throw new Error(
`doSnodeBatchRequest - sessionRpc could not talk to ${targetNode.ip}:${targetNode.port}`
`doSnodeBatchRequestNoRetries - sessionRpc could not talk to ${targetNode.ip}:${targetNode.port}`
);
}
const decoded = decodeBatchRequest(result);
@ -76,7 +81,19 @@ async function doSnodeBatchRequest(
return decoded;
}
async function doUnsignedSnodeBatchRequest(
/**
* This function can be called to make the sign the subrequests and then call doSnodeBatchRequestNoRetries with the signed requests.
*
* Note: this function does not retry.
*
* @param unsignedSubRequests the unsigned sub requests to make
* @param targetNode the snode to make the request to
* @param timeout the max timeout to wait for a reply
* @param associatedWith the pubkey associated with this request (used to remove snode failing to reply from that users' swarm)
* @param method the type of request to make batch or sequence
* @returns
*/
async function doUnsignedSnodeBatchRequestNoRetries(
unsignedSubRequests: Array<RawSnodeSubRequests>,
targetNode: Snode,
timeout: number,
@ -84,7 +101,7 @@ async function doUnsignedSnodeBatchRequest(
method: MethodBatchType = 'batch'
): Promise<NotEmptyArrayOfBatchResults> {
const signedSubRequests = await MessageSender.signSubRequests(unsignedSubRequests);
return BatchRequests.doSnodeBatchRequest(
return BatchRequests.doSnodeBatchRequestNoRetries(
signedSubRequests,
targetNode,
timeout,
@ -121,6 +138,6 @@ function decodeBatchRequest(snodeResponse: SnodeResponse): NotEmptyArrayOfBatchR
}
export const BatchRequests = {
doSnodeBatchRequest,
doUnsignedSnodeBatchRequest,
doSnodeBatchRequestNoRetries,
doUnsignedSnodeBatchRequestNoRetries,
};

@ -140,13 +140,13 @@ export async function processExpireRequestResponse(
type UpdatedExpiryWithHashes = { messageHashes: Array<string>; updatedExpiryMs: number };
type UpdatedExpiryWithHash = { messageHash: string; updatedExpiryMs: number };
async function updateExpiryOnNodes(
async function updateExpiryOnNodesNoRetries(
targetNode: Snode,
ourPubKey: string,
expireRequests: Array<UpdateExpiryOnNodeUserSubRequest>
): Promise<Array<UpdatedExpiryWithHash>> {
try {
const result = await BatchRequests.doUnsignedSnodeBatchRequest(
const result = await BatchRequests.doUnsignedSnodeBatchRequestNoRetries(
expireRequests,
targetNode,
4000,
@ -407,7 +407,7 @@ export async function expireMessagesOnSnode(
async () => {
const targetNode = await SnodePool.getNodeFromSwarmOrThrow(ourPubKey);
return updateExpiryOnNodes(targetNode, ourPubKey, chunkRequest);
return updateExpiryOnNodesNoRetries(targetNode, ourPubKey, chunkRequest);
},
{
retries: 3,

@ -39,14 +39,14 @@ export async function processGetExpiriesRequestResponse(
return results;
}
async function getExpiriesFromNodes(
async function getExpiriesFromNodesNoRetries(
targetNode: Snode,
messageHashes: Array<string>,
associatedWith: PubkeyType
) {
try {
const expireRequest = new GetExpiriesFromNodeSubRequest({ messagesHashes: messageHashes });
const result = await BatchRequests.doUnsignedSnodeBatchRequest(
const result = await BatchRequests.doUnsignedSnodeBatchRequestNoRetries(
[expireRequest],
targetNode,
4000,
@ -67,7 +67,7 @@ async function getExpiriesFromNodes(
const firstResult = result[0];
if (firstResult.code !== 200) {
throw Error(`getExpiriesFromNodes result is not 200 but ${firstResult.code}`);
throw Error(`getExpiriesFromNodesNoRetries result is not 200 but ${firstResult.code}`);
}
// expirationResults is a record of {messageHash: currentExpiry}
@ -122,7 +122,7 @@ export async function getExpiriesFromSnode({ messagesHashes }: WithMessagesHashe
async () => {
const targetNode = await SnodePool.getNodeFromSwarmOrThrow(ourPubKey);
return getExpiriesFromNodes(targetNode, messagesHashes, ourPubKey);
return getExpiriesFromNodesNoRetries(targetNode, messagesHashes, ourPubKey);
},
{
retries: 3,

@ -12,7 +12,12 @@ import { BatchRequests } from './batchRequest';
const getNetworkTime = async (snode: Snode): Promise<string | number> => {
const subrequest = new NetworkTimeSubRequest();
const result = await BatchRequests.doUnsignedSnodeBatchRequest([subrequest], snode, 4000, null);
const result = await BatchRequests.doUnsignedSnodeBatchRequestNoRetries(
[subrequest],
snode,
4000,
null
);
if (!result || !result.length) {
window?.log?.warn(`getNetworkTime on ${snode.ip}:${snode.port} returned falsish value`, result);
throw new Error('getNetworkTime: Invalid result');

@ -13,7 +13,7 @@ import { SnodePool } from './snodePool';
async function getSnodePoolFromSnode(targetNode: Snode): Promise<Array<Snode>> {
const subrequest = new GetServiceNodesSubRequest();
const results = await BatchRequests.doUnsignedSnodeBatchRequest(
const results = await BatchRequests.doUnsignedSnodeBatchRequestNoRetries(
[subrequest],
targetNode,
4000,

@ -19,7 +19,7 @@ async function requestSnodesForPubkeyWithTargetNodeRetryable(
}
const subrequest = new SwarmForSubRequest(pubkey);
const result = await BatchRequests.doUnsignedSnodeBatchRequest(
const result = await BatchRequests.doUnsignedSnodeBatchRequestNoRetries(
[subrequest],
targetNode,
4000,

@ -808,7 +808,7 @@ async function incrementBadSnodeCountOrDrop({
* This call tries to send the request via onion. If we get a bad path, it handles the snode removing of the swarm and snode pool.
* But the caller needs to handle the retry (and rebuild the path on his side if needed)
*/
async function sendOnionRequestHandlingSnodeEject({
async function sendOnionRequestHandlingSnodeEjectNoRetries({
destSnodeX25519,
finalDestOptions,
nodePath,
@ -828,7 +828,7 @@ async function sendOnionRequestHandlingSnodeEject({
throwErrors: boolean;
}): Promise<SnodeResponse | SnodeResponseV4 | undefined> {
// this sendOnionRequestNoRetries() call has to be the only one like this.
// If you need to call it, call it through sendOnionRequestHandlingSnodeEject because this is the one handling path rebuilding and known errors
// If you need to call it, call it through sendOnionRequestHandlingSnodeEjectNoRetries because this is the one handling path rebuilding and known errors
let response;
let decodingSymmetricKey;
try {
@ -844,7 +844,7 @@ async function sendOnionRequestHandlingSnodeEject({
if (window.sessionFeatureFlags?.debug.debugOnionRequests) {
window.log.info(
`sendOnionRequestHandlingSnodeEject: sendOnionRequestNoRetries: useV4:${useV4} destSnodeX25519:${destSnodeX25519}; \nfinalDestOptions:${JSON.stringify(
`sendOnionRequestHandlingSnodeEjectNoRetries: sendOnionRequestNoRetries: useV4:${useV4} destSnodeX25519:${destSnodeX25519}; \nfinalDestOptions:${JSON.stringify(
finalDestOptions
)}; \nfinalRelayOptions:${JSON.stringify(finalRelayOptions)}\n\n result: ${JSON.stringify(
result
@ -1098,14 +1098,14 @@ const sendOnionRequestNoRetries = async ({
return { response, decodingSymmetricKey: destCtx.symmetricKey };
};
async function sendOnionRequestSnodeDest(
async function sendOnionRequestSnodeDestNoRetries(
onionPath: Array<Snode>,
targetNode: Snode,
headers: Record<string, any>,
plaintext: string | null,
associatedWith?: string
) {
return Onions.sendOnionRequestHandlingSnodeEject({
return Onions.sendOnionRequestHandlingSnodeEjectNoRetries({
nodePath: onionPath,
destSnodeX25519: targetNode.pubkey_x25519,
finalDestOptions: {
@ -1126,7 +1126,7 @@ function getPathString(pathObjArr: Array<{ ip: string; port: number }>): string
/**
* If the fetch throws a retryable error we retry this call with a new path at most 3 times. If another error happens, we return it. If we have a result we just return it.
*/
async function lokiOnionFetch({
async function lokiOnionFetchWithRetries({
targetNode,
associatedWith,
body,
@ -1142,7 +1142,7 @@ async function lokiOnionFetch({
async () => {
// Get a path excluding `targetNode`:
const path = await OnionPaths.getOnionPath({ toExclude: targetNode });
const result = await sendOnionRequestSnodeDest(
const result = await sendOnionRequestSnodeDestNoRetries(
path,
targetNode,
headers,
@ -1179,12 +1179,12 @@ async function lokiOnionFetch({
}
export const Onions = {
sendOnionRequestHandlingSnodeEject,
sendOnionRequestHandlingSnodeEjectNoRetries,
incrementBadSnodeCountOrDrop,
decodeOnionResult,
lokiOnionFetch,
lokiOnionFetchWithRetries,
getPathString,
sendOnionRequestSnodeDest,
sendOnionRequestSnodeDestNoRetries,
processOnionResponse,
processOnionResponseV4,
isFinalDestinationSnode,

@ -29,7 +29,7 @@ async function getSessionIDForOnsName(onsNameCase: string) {
const promises = range(0, validationCount).map(async () => {
const targetNode = await SnodePool.getRandomSnode();
const results = await BatchRequests.doUnsignedSnodeBatchRequest(
const results = await BatchRequests.doUnsignedSnodeBatchRequestNoRetries(
[subRequest],
targetNode,
4000,

@ -193,7 +193,7 @@ async function buildRetrieveRequest(
return retrieveRequestsParams;
}
async function retrieveNextMessages(
async function retrieveNextMessagesNoRetries(
targetNode: Snode,
associatedWith: string,
namespacesAndLastHashes: Array<NamespaceAndLastHash>,
@ -209,8 +209,7 @@ async function retrieveNextMessages(
// let exceptions bubble up
// no retry for this one as this a call we do every few seconds while polling for messages
const results = await BatchRequests.doUnsignedSnodeBatchRequest(
const results = await BatchRequests.doUnsignedSnodeBatchRequestNoRetries(
rawRequests,
targetNode,
4000,
@ -239,7 +238,7 @@ async function retrieveNextMessages(
const firstResult = results[0];
if (firstResult.code !== 200) {
window?.log?.warn(`retrieveNextMessages result is not 200 but ${firstResult.code}`);
window?.log?.warn(`retrieveNextMessagesNoRetries result is not 200 but ${firstResult.code}`);
throw new Error(
`_retrieveNextMessages - retrieve result is not 200 with ${targetNode.ip}:${targetNode.port} but ${firstResult.code}`
);
@ -268,4 +267,4 @@ async function retrieveNextMessages(
}
}
export const SnodeAPIRetrieve = { retrieveNextMessages, buildRetrieveRequest };
export const SnodeAPIRetrieve = { retrieveNextMessagesNoRetries, buildRetrieveRequest };

@ -20,9 +20,10 @@ export interface LokiFetchOptions {
/**
* A small wrapper around node-fetch which deserializes response
* returns insecureNodeFetch response or false
* returned by insecureNodeFetch or false.
* Does not do any retries, nor eject snodes if needed
*/
async function doRequest({
async function doRequestNoRetries({
options,
url,
associatedWith,
@ -51,7 +52,7 @@ async function doRequest({
? true
: window.sessionFeatureFlags?.useOnionRequests;
if (useOnionRequests && targetNode) {
const fetchResult = await Onions.lokiOnionFetch({
const fetchResult = await Onions.lokiOnionFetchWithRetries({
targetNode,
body: fetchOptions.body,
headers: fetchOptions.headers,
@ -109,7 +110,7 @@ async function doRequest({
* -> if the targetNode gets too many errors => we will need to try to do this request again with another target node
* The
*/
async function snodeRpc(
async function snodeRpcNoRetries(
{
method,
params,
@ -139,7 +140,7 @@ async function snodeRpc(
agent: null,
};
return doRequest({
return doRequestNoRetries({
url,
options: fetchOptions,
targetNode,
@ -148,4 +149,4 @@ async function snodeRpc(
});
}
export const SessionRpc = { snodeRpc };
export const SessionRpc = { snodeRpcNoRetries };

@ -519,7 +519,7 @@ export class SwarmPolling {
})
);
let results = await SnodeAPIRetrieve.retrieveNextMessages(
let results = await SnodeAPIRetrieve.retrieveNextMessagesNoRetries(
node,
pubkey,
namespacesAndLastHashes,

@ -159,7 +159,7 @@ const sendViaOnionV4ToNonSnodeWithRetries = async (
* call above will call us again with the same params but a different path.
* If the error is not recoverable, it throws a pRetry.AbortError.
*/
const onionV4Response = await Onions.sendOnionRequestHandlingSnodeEject({
const onionV4Response = await Onions.sendOnionRequestHandlingSnodeEjectNoRetries({
nodePath: pathNodes,
destSnodeX25519: destinationX25519Key,
finalDestOptions: payloadObj,
@ -171,7 +171,7 @@ const sendViaOnionV4ToNonSnodeWithRetries = async (
if (window.sessionFeatureFlags?.debug.debugNonSnodeRequests) {
window.log.info(
'sendViaOnionV4ToNonSnodeWithRetries: sendOnionRequestHandlingSnodeEject returned: ',
'sendViaOnionV4ToNonSnodeWithRetries: sendOnionRequestHandlingSnodeEjectNoRetries returned: ',
JSON.stringify(onionV4Response)
);
}

@ -228,7 +228,7 @@ async function sendSingleMessage({
}
const targetNode = await SnodePool.getNodeFromSwarmOrThrow(destination);
const batchResult = await BatchRequests.doUnsignedSnodeBatchRequest(
const batchResult = await BatchRequests.doUnsignedSnodeBatchRequestNoRetries(
subRequests,
targetNode,
6000,
@ -380,7 +380,7 @@ async function sendMessagesDataToSnode(
const targetNode = await SnodePool.getNodeFromSwarmOrThrow(asssociatedWith);
try {
const storeResults = await BatchRequests.doUnsignedSnodeBatchRequest(
const storeResults = await BatchRequests.doUnsignedSnodeBatchRequestNoRetries(
rawRequests,
targetNode,
4000,
@ -390,10 +390,10 @@ async function sendMessagesDataToSnode(
if (!storeResults || !storeResults.length) {
window?.log?.warn(
`SessionSnodeAPI::doSnodeBatchRequest on ${targetNode.ip}:${targetNode.port} returned falsish value`,
`SessionSnodeAPI::doUnsignedSnodeBatchRequestNoRetries on ${targetNode.ip}:${targetNode.port} returned falsish value`,
storeResults
);
throw new Error('doSnodeBatchRequest: Invalid result');
throw new Error('doUnsignedSnodeBatchRequestNoRetries: Invalid result');
}
const firstResult = storeResults[0];

@ -49,12 +49,15 @@ describe('MessageSender', () => {
describe('send', () => {
const ourNumber = TestUtils.generateFakePubKeyStr();
let sessionMessageAPISendStub: TypedStub<typeof MessageSender, 'sendMessagesDataToSnode'>;
let doSnodeBatchRequestStub: TypedStub<typeof BatchRequests, 'doSnodeBatchRequest'>;
let doSnodeBatchRequestStub: TypedStub<typeof BatchRequests, 'doSnodeBatchRequestNoRetries'>;
let encryptStub: sinon.SinonStub<[PubKey, Uint8Array, SignalService.Envelope.Type]>;
beforeEach(() => {
sessionMessageAPISendStub = Sinon.stub(MessageSender, 'sendMessagesDataToSnode').resolves();
doSnodeBatchRequestStub = Sinon.stub(BatchRequests, 'doSnodeBatchRequest').resolves();
doSnodeBatchRequestStub = Sinon.stub(
BatchRequests,
'doSnodeBatchRequestNoRetries'
).resolves();
stubData('getMessageById').resolves();
encryptStub = Sinon.stub(MessageEncrypter, 'encrypt').resolves({
@ -317,7 +320,7 @@ describe('MessageSender', () => {
it('should call sendOnionRequestHandlingSnodeEjectStub', async () => {
const sendOnionRequestHandlingSnodeEjectStub = Sinon.stub(
Onions,
'sendOnionRequestHandlingSnodeEject'
'sendOnionRequestHandlingSnodeEjectNoRetries'
).resolves({} as any);
Sinon.stub(OnionV4, 'decodeV4Response').returns({
metadata: { code: 200 },
@ -336,7 +339,7 @@ describe('MessageSender', () => {
it('should retry sendOnionRequestHandlingSnodeEjectStub ', async () => {
const message = TestUtils.generateOpenGroupVisibleMessage();
const roomInfos = TestUtils.generateOpenGroupV2RoomInfos();
Sinon.stub(Onions, 'sendOnionRequestHandlingSnodeEject').resolves({} as any);
Sinon.stub(Onions, 'sendOnionRequestHandlingSnodeEjectNoRetries').resolves({} as any);
Sinon.stub(OnionSending, 'getMinTimeoutForSogs').returns(5);
@ -356,7 +359,7 @@ describe('MessageSender', () => {
it('should not retry more than 3 sendOnionRequestHandlingSnodeEjectStub ', async () => {
const message = TestUtils.generateOpenGroupVisibleMessage();
const roomInfos = TestUtils.generateOpenGroupV2RoomInfos();
Sinon.stub(Onions, 'sendOnionRequestHandlingSnodeEject').resolves({} as any);
Sinon.stub(Onions, 'sendOnionRequestHandlingSnodeEjectNoRetries').resolves({} as any);
Sinon.stub(OnionSending, 'getMinTimeoutForSogs').returns(5);
const decodev4responseStub = Sinon.stub(OnionV4, 'decodeV4Response');

@ -74,7 +74,7 @@ describe('SwarmPolling:pollForAllKeys', () => {
TestUtils.stubLibSessionWorker(undefined);
Sinon.stub(SnodePool, 'getSwarmFor').resolves(generateFakeSnodes(5));
Sinon.stub(SnodeAPIRetrieve, 'retrieveNextMessages').resolves([]);
Sinon.stub(SnodeAPIRetrieve, 'retrieveNextMessagesNoRetries').resolves([]);
TestUtils.stubWindow('inboxStore', undefined);
TestUtils.stubWindow('getGlobalOnlineStatus', () => true);

Loading…
Cancel
Save