You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.2 KiB
TypeScript
152 lines
4.2 KiB
TypeScript
import { GroupPubkeyType, PubkeyType } from 'libsession_util_nodejs';
|
|
import { isNumber } from 'lodash';
|
|
import { v4 } from 'uuid';
|
|
import { UserUtils } from '../..';
|
|
import {
|
|
MetaGroupWrapperActions,
|
|
UserGroupsWrapperActions,
|
|
} from '../../../../webworker/workers/browser/libsession_worker_interface';
|
|
import { SnodeNamespaces } from '../../../apis/snode_api/namespaces';
|
|
import { SnodeGroupSignature } from '../../../apis/snode_api/signature/groupSignature';
|
|
import { getMessageQueue } from '../../../sending';
|
|
import { PubKey } from '../../../types';
|
|
import { runners } from '../JobRunner';
|
|
import {
|
|
AddJobCheckReturn,
|
|
GroupPromotePersistedData,
|
|
PersistedJob,
|
|
RunJobResult,
|
|
} from '../PersistedJob';
|
|
|
|
const defaultMsBetweenRetries = 10000;
|
|
const defaultMaxAttemps = 1;
|
|
|
|
type JobExtraArgs = {
|
|
groupPk: GroupPubkeyType;
|
|
member: PubkeyType;
|
|
};
|
|
|
|
export function shouldAddJob(args: JobExtraArgs) {
|
|
if (UserUtils.isUsFromCache(args.member)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
async function addJob({ groupPk, member }: JobExtraArgs) {
|
|
if (shouldAddJob({ groupPk, member })) {
|
|
const groupPromoteJob = new GroupPromoteJob({
|
|
groupPk,
|
|
member,
|
|
nextAttemptTimestamp: Date.now(),
|
|
});
|
|
window.log.debug(`addGroupPromoteJob: adding group promote for ${groupPk}:${member} `);
|
|
await runners.groupPromoteJobRunner.addJob(groupPromoteJob);
|
|
}
|
|
}
|
|
|
|
class GroupPromoteJob extends PersistedJob<GroupPromotePersistedData> {
|
|
constructor({
|
|
groupPk,
|
|
member,
|
|
nextAttemptTimestamp,
|
|
maxAttempts,
|
|
currentRetry,
|
|
identifier,
|
|
}: Pick<GroupPromotePersistedData, 'groupPk' | 'member'> &
|
|
Partial<
|
|
Pick<
|
|
GroupPromotePersistedData,
|
|
| 'nextAttemptTimestamp'
|
|
| 'identifier'
|
|
| 'maxAttempts'
|
|
| 'delayBetweenRetries'
|
|
| 'currentRetry'
|
|
>
|
|
>) {
|
|
super({
|
|
jobType: 'GroupPromoteJobType',
|
|
identifier: identifier || v4(),
|
|
member,
|
|
groupPk,
|
|
delayBetweenRetries: defaultMsBetweenRetries,
|
|
maxAttempts: isNumber(maxAttempts) ? maxAttempts : defaultMaxAttemps,
|
|
nextAttemptTimestamp: nextAttemptTimestamp || Date.now() + defaultMsBetweenRetries,
|
|
currentRetry: isNumber(currentRetry) ? currentRetry : 0,
|
|
});
|
|
}
|
|
|
|
public async run(): Promise<RunJobResult> {
|
|
const { groupPk, member, jobType, identifier } = this.persistedData;
|
|
|
|
window.log.info(
|
|
`running job ${jobType} with groupPk:"${groupPk}" member: ${member} id:"${identifier}" `
|
|
);
|
|
const group = await UserGroupsWrapperActions.getGroup(groupPk);
|
|
if (!group || !group.secretKey || !group.name) {
|
|
window.log.warn(`GroupPromoteJob: Did not find group in wrapper or no valid info in wrapper`);
|
|
return RunJobResult.PermanentFailure;
|
|
}
|
|
|
|
if (UserUtils.isUsFromCache(member)) {
|
|
return RunJobResult.Success;
|
|
}
|
|
let failed = true;
|
|
try {
|
|
const message = await SnodeGroupSignature.getGroupPromoteMessage({
|
|
member,
|
|
secretKey: group.secretKey,
|
|
groupPk,
|
|
});
|
|
|
|
const storedAt = await getMessageQueue().sendTo1o1NonDurably({
|
|
message,
|
|
namespace: SnodeNamespaces.Default,
|
|
pubkey: PubKey.cast(member),
|
|
});
|
|
if (storedAt !== null) {
|
|
failed = false;
|
|
}
|
|
} finally {
|
|
try {
|
|
await MetaGroupWrapperActions.memberSetPromoted(groupPk, member, failed);
|
|
} catch (e) {
|
|
window.log.warn('GroupPromoteJob memberSetPromoted failed with', e.message);
|
|
}
|
|
}
|
|
// return true so this job is marked as a success and we don't need to retry it
|
|
return RunJobResult.Success;
|
|
}
|
|
|
|
public serializeJob(): GroupPromotePersistedData {
|
|
return super.serializeBase();
|
|
}
|
|
|
|
public nonRunningJobsToRemove(_jobs: Array<GroupPromotePersistedData>) {
|
|
return [];
|
|
}
|
|
|
|
public addJobCheck(jobs: Array<GroupPromotePersistedData>): AddJobCheckReturn {
|
|
// avoid adding the same job if the exact same one is already planned
|
|
const hasSameJob = jobs.some(j => {
|
|
return j.groupPk === this.persistedData.groupPk && j.member === this.persistedData.member;
|
|
});
|
|
|
|
if (hasSameJob) {
|
|
return 'skipAddSameJobPresent';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public getJobTimeoutMs(): number {
|
|
return 15000;
|
|
}
|
|
}
|
|
|
|
export const GroupPromote = {
|
|
GroupPromoteJob,
|
|
addJob,
|
|
};
|