add name debug info to fetchable-pair-verifier
This commit is contained in:
parent
366022cebb
commit
6e95ec4cec
@ -27,6 +27,7 @@ export class AutoVerifierWithArg<T, K> {
|
|||||||
private primaryFunc: (query: K) => Promise<T | null>,
|
private primaryFunc: (query: K) => Promise<T | null>,
|
||||||
private trustedFunc: (query: K) => Promise<T | null>,
|
private trustedFunc: (query: K) => Promise<T | null>,
|
||||||
private verifyFunc: (query: K, primaryResult: T | null, trustedResult: T | null) => Promise<boolean>,
|
private verifyFunc: (query: K, primaryResult: T | null, trustedResult: T | null) => Promise<boolean>,
|
||||||
|
private name: string | null = null, // for debugging purposes
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
static createStandardPartialMessageListAutoVerifier<T extends WithEquals<T> & { id: string }>(
|
static createStandardPartialMessageListAutoVerifier<T extends WithEquals<T> & { id: string }>(
|
||||||
@ -37,6 +38,7 @@ export class AutoVerifierWithArg<T, K> {
|
|||||||
changesType: AutoVerifierChangesType,
|
changesType: AutoVerifierChangesType,
|
||||||
changes: Changes<T>,
|
changes: Changes<T>,
|
||||||
) => Promise<boolean>,
|
) => Promise<boolean>,
|
||||||
|
name: string | null = null,
|
||||||
) {
|
) {
|
||||||
return new AutoVerifierWithArg<T[], PartialMessageListQuery>(
|
return new AutoVerifierWithArg<T[], PartialMessageListQuery>(
|
||||||
query => `ch#${query.channelId} mo#${query.messageOrderId}->${query.number}`,
|
query => `ch#${query.channelId} mo#${query.messageOrderId}->${query.number}`,
|
||||||
@ -57,6 +59,7 @@ export class AutoVerifierWithArg<T, K> {
|
|||||||
const changesType = AutoVerifier.getListChangesType<T>(primaryResult, trustedResult, changes);
|
const changesType = AutoVerifier.getListChangesType<T>(primaryResult, trustedResult, changes);
|
||||||
return await changesFunc(query, changesType, changes);
|
return await changesFunc(query, changesType, changes);
|
||||||
},
|
},
|
||||||
|
name,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +72,7 @@ export class AutoVerifierWithArg<T, K> {
|
|||||||
primaryResult: T | null,
|
primaryResult: T | null,
|
||||||
trustedResult: T | null,
|
trustedResult: T | null,
|
||||||
) => Promise<boolean>,
|
) => Promise<boolean>,
|
||||||
|
name: string | null = null,
|
||||||
) {
|
) {
|
||||||
return new AutoVerifierWithArg<T, IDQuery>(
|
return new AutoVerifierWithArg<T, IDQuery>(
|
||||||
query => `id#${query.id}`,
|
query => `id#${query.id}`,
|
||||||
@ -78,6 +82,7 @@ export class AutoVerifierWithArg<T, K> {
|
|||||||
const changesType = AutoVerifier.getSingleChangesType<T>(primaryResult, trustedResult);
|
const changesType = AutoVerifier.getSingleChangesType<T>(primaryResult, trustedResult);
|
||||||
return await changesFunc(query, changesType, primaryResult, trustedResult);
|
return await changesFunc(query, changesType, primaryResult, trustedResult);
|
||||||
},
|
},
|
||||||
|
name,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +122,7 @@ export class AutoVerifierWithArg<T, K> {
|
|||||||
async () => await this.trustedFunc(query),
|
async () => await this.trustedFunc(query),
|
||||||
async (primaryResult: T | null, trustedResult: T | null) =>
|
async (primaryResult: T | null, trustedResult: T | null) =>
|
||||||
await this.verifyFunc(query, primaryResult, trustedResult),
|
await this.verifyFunc(query, primaryResult, trustedResult),
|
||||||
|
`${this.name}::${token.slice(0, 8)}`
|
||||||
);
|
);
|
||||||
this.tokenAutoVerifiers.set(token, autoVerifier);
|
this.tokenAutoVerifiers.set(token, autoVerifier);
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ export class AutoVerifier<T> {
|
|||||||
// we've been invalidated while we were waiting for the trusted result!
|
// we've been invalidated while we were waiting for the trusted result!
|
||||||
// TODO: This happens when a socket fetch is sent before the socket is connected to.
|
// TODO: This happens when a socket fetch is sent before the socket is connected to.
|
||||||
console.warn(
|
console.warn(
|
||||||
'RARE ALERT: we got unverified while trying to fetch a trusted promise for verification!',
|
`RARE ALERT: ${this.name || 'we'} got unverified while trying to fetch a trusted promise for verification!`,
|
||||||
new Error(),
|
new Error(),
|
||||||
);
|
);
|
||||||
if (this.trustedPromise === null) {
|
if (this.trustedPromise === null) {
|
||||||
@ -281,8 +281,6 @@ export class AutoVerifier<T> {
|
|||||||
this.trustedPromise = null;
|
this.trustedPromise = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this actually could be quite common
|
|
||||||
//console.warn('RARE ALERT: we got unverified during verification!');
|
|
||||||
// ** complexity:
|
// ** complexity:
|
||||||
// if primaryUpToDate is false or we got unverified during verification, this path will still return
|
// if primaryUpToDate is false or we got unverified during verification, this path will still return
|
||||||
// the trustedResult that was passed to the verify function
|
// the trustedResult that was passed to the verify function
|
||||||
@ -320,7 +318,7 @@ export class AutoVerifier<T> {
|
|||||||
if (this.trustedPromise !== origTrustedPromise) {
|
if (this.trustedPromise !== origTrustedPromise) {
|
||||||
// we've been invalidated while we were waiting for the trusted result!
|
// we've been invalidated while we were waiting for the trusted result!
|
||||||
console.warn(
|
console.warn(
|
||||||
'ULTRA RARE ALERT: we got unverified while awaiting a trusted promise another path was verifying!',
|
`ULTRA RARE ALERT: ${this.name || 'we'} got unverified while awaiting a trusted promise another path was verifying!`,
|
||||||
);
|
);
|
||||||
await tryResolveTrustedPromise();
|
await tryResolveTrustedPromise();
|
||||||
return;
|
return;
|
||||||
@ -330,7 +328,7 @@ export class AutoVerifier<T> {
|
|||||||
if (this.trustedPromise !== origTrustedPromise) {
|
if (this.trustedPromise !== origTrustedPromise) {
|
||||||
// we've been invalidated while we were waiting for the verify!
|
// we've been invalidated while we were waiting for the verify!
|
||||||
console.warn(
|
console.warn(
|
||||||
'ULTRA RARE ALERT: we got unverified while awaiting a verify promise another path was calling!',
|
`ULTRA RARE ALERT: ${this.name || 'we'} got unverified while awaiting a verify promise another path was calling!`,
|
||||||
);
|
);
|
||||||
// ** complexity:
|
// ** complexity:
|
||||||
// if primaryUpToDate is false or we got unverified during verification, this path will still return
|
// if primaryUpToDate is false or we got unverified during verification, this path will still return
|
||||||
|
@ -4,13 +4,13 @@ import Logger from '../../logger/logger';
|
|||||||
const LOG = Logger.create(__filename, electronConsole);
|
const LOG = Logger.create(__filename, electronConsole);
|
||||||
|
|
||||||
import { Changes, Channel, GuildMetadata, Member, Message, Resource, Token } from './data-types';
|
import { Changes, Channel, GuildMetadata, Member, Message, Resource, Token } from './data-types';
|
||||||
import { AsyncFetchable, Fetchable, Lackable, Conflictable, Ensurable } from './guild-types';
|
import { AsyncFetchable, Fetchable, Lackable, Conflictable } from './guild-types';
|
||||||
import { AutoVerifier, AutoVerifierChangesType } from './auto-verifier';
|
import { AutoVerifier, AutoVerifierChangesType } from './auto-verifier';
|
||||||
import { AutoVerifierWithArg, PartialMessageListQuery, IDQuery } from './auto-verifier-with-args';
|
import { AutoVerifierWithArg, PartialMessageListQuery, IDQuery } from './auto-verifier-with-args';
|
||||||
import { EventEmitter } from 'tsee';
|
import { EventEmitter } from 'tsee';
|
||||||
|
|
||||||
/** uses a primary fetchable and trusted fetchable and verifys the results. Can be chained together with itself as a trusted fetchable! */
|
/** uses a primary fetchable and trusted fetchable and verifys the results. Can be chained together with itself as a trusted fetchable! */
|
||||||
export default class PairVerifierFetchable extends EventEmitter<Conflictable> implements AsyncFetchable, Ensurable {
|
export default class PairVerifierFetchable extends EventEmitter<Conflictable> implements AsyncFetchable {
|
||||||
private readonly fetchMetadataVerifier: AutoVerifier<GuildMetadata>;
|
private readonly fetchMetadataVerifier: AutoVerifier<GuildMetadata>;
|
||||||
private readonly fetchMembersVerifier: AutoVerifier<Member[]>;
|
private readonly fetchMembersVerifier: AutoVerifier<Member[]>;
|
||||||
private readonly fetchChannelsVerifier: AutoVerifier<Channel[]>;
|
private readonly fetchChannelsVerifier: AutoVerifier<Channel[]>;
|
||||||
@ -22,7 +22,7 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
|
|||||||
public readonly fetchMessagesBeforeVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>;
|
public readonly fetchMessagesBeforeVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>;
|
||||||
public readonly fetchMessagesAfterVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>;
|
public readonly fetchMessagesAfterVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>;
|
||||||
|
|
||||||
constructor(private primary: Fetchable & Lackable, private trusted: Fetchable & Ensurable, private name: string | null = null) {
|
constructor(private primary: Fetchable & Lackable, private trusted: Fetchable, private name: string | null = null) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
if (trusted instanceof PairVerifierFetchable) {
|
if (trusted instanceof PairVerifierFetchable) {
|
||||||
@ -39,18 +39,21 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
|
|||||||
async () => await this.primary.fetchMetadata(),
|
async () => await this.primary.fetchMetadata(),
|
||||||
async () => await this.trusted.fetchMetadata(),
|
async () => await this.trusted.fetchMetadata(),
|
||||||
this.handleMetadataConflict.bind(this),
|
this.handleMetadataConflict.bind(this),
|
||||||
|
`${this.name}#fetchMetadata`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fetchMembersVerifier = AutoVerifier.createStandardListAutoVerifier<Member>(
|
this.fetchMembersVerifier = AutoVerifier.createStandardListAutoVerifier<Member>(
|
||||||
async () => await this.primary.fetchMembers(),
|
async () => await this.primary.fetchMembers(),
|
||||||
async () => await this.trusted.fetchMembers(),
|
async () => await this.trusted.fetchMembers(),
|
||||||
this.handleMembersConflict.bind(this),
|
this.handleMembersConflict.bind(this),
|
||||||
|
`${this.name}#fetchMembers`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fetchChannelsVerifier = AutoVerifier.createStandardListAutoVerifier<Channel>(
|
this.fetchChannelsVerifier = AutoVerifier.createStandardListAutoVerifier<Channel>(
|
||||||
async () => await this.primary.fetchChannels(),
|
async () => await this.primary.fetchChannels(),
|
||||||
async () => await this.trusted.fetchChannels(),
|
async () => await this.trusted.fetchChannels(),
|
||||||
this.handleChannelsConflict.bind(this),
|
this.handleChannelsConflict.bind(this),
|
||||||
|
`${this.name}#fetchChannels`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fetchTokensVerifier = AutoVerifier.createStandardListAutoVerifier<Token>(
|
this.fetchTokensVerifier = AutoVerifier.createStandardListAutoVerifier<Token>(
|
||||||
@ -59,12 +62,14 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
|
|||||||
async () => await this.primary.fetchTokens(),
|
async () => await this.primary.fetchTokens(),
|
||||||
async () => await this.trusted.fetchTokens(),
|
async () => await this.trusted.fetchTokens(),
|
||||||
this.handleTokensConflict.bind(this),
|
this.handleTokensConflict.bind(this),
|
||||||
|
`${this.name}#fetchTokens`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fetchResourceVerifier = AutoVerifierWithArg.createStandardIDQueriedSingleAutoVerifier<Resource>(
|
this.fetchResourceVerifier = AutoVerifierWithArg.createStandardIDQueriedSingleAutoVerifier<Resource>(
|
||||||
async (query: IDQuery) => await this.primary.fetchResource(query.id),
|
async (query: IDQuery) => await this.primary.fetchResource(query.id),
|
||||||
async (query: IDQuery) => await this.trusted.fetchResource(query.id),
|
async (query: IDQuery) => await this.trusted.fetchResource(query.id),
|
||||||
this.handleResourceConflict.bind(this),
|
this.handleResourceConflict.bind(this),
|
||||||
|
`${this.name}#fetchResource`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fetchMessagesRecentVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
|
this.fetchMessagesRecentVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
|
||||||
@ -73,6 +78,7 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
|
|||||||
async (query: PartialMessageListQuery) =>
|
async (query: PartialMessageListQuery) =>
|
||||||
await this.trusted.fetchMessagesRecent(query.channelId, query.number),
|
await this.trusted.fetchMessagesRecent(query.channelId, query.number),
|
||||||
this.handleMessagesConflict.bind(this),
|
this.handleMessagesConflict.bind(this),
|
||||||
|
`${this.name}#fetchMessagesRecent`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fetchMessagesBeforeVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
|
this.fetchMessagesBeforeVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
|
||||||
@ -81,6 +87,7 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
|
|||||||
async (query: PartialMessageListQuery) =>
|
async (query: PartialMessageListQuery) =>
|
||||||
await this.trusted.fetchMessagesBefore(query.channelId, query.messageOrderId as string, query.number),
|
await this.trusted.fetchMessagesBefore(query.channelId, query.messageOrderId as string, query.number),
|
||||||
this.handleMessagesConflict.bind(this),
|
this.handleMessagesConflict.bind(this),
|
||||||
|
`${this.name}#fetchMessagesBefore`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fetchMessagesAfterVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
|
this.fetchMessagesAfterVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
|
||||||
@ -89,13 +96,10 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
|
|||||||
async (query: PartialMessageListQuery) =>
|
async (query: PartialMessageListQuery) =>
|
||||||
await this.trusted.fetchMessagesAfter(query.channelId, query.messageOrderId as string, query.number),
|
await this.trusted.fetchMessagesAfter(query.channelId, query.messageOrderId as string, query.number),
|
||||||
this.handleMessagesConflict.bind(this),
|
this.handleMessagesConflict.bind(this),
|
||||||
|
`${this.name}#fetchMessagesAfter`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async ensureVerified(): Promise<void> {
|
|
||||||
/* do nothing */
|
|
||||||
}
|
|
||||||
|
|
||||||
async handleMetadataConflict(
|
async handleMetadataConflict(
|
||||||
changesType: AutoVerifierChangesType,
|
changesType: AutoVerifierChangesType,
|
||||||
primaryMetadata: GuildMetadata | null,
|
primaryMetadata: GuildMetadata | null,
|
||||||
|
@ -59,8 +59,8 @@ export default class CombinedGuild
|
|||||||
this.personalDBGuild = new PersonalDBGuild(personalDB, this.id, this.memberId);
|
this.personalDBGuild = new PersonalDBGuild(personalDB, this.id, this.memberId);
|
||||||
this.socketGuild = new SocketGuild(socket, socketVerifier);
|
this.socketGuild = new SocketGuild(socket, socketVerifier);
|
||||||
|
|
||||||
const diskSocket = new PairVerifierFetchable(this.personalDBGuild, this.socketGuild, 'Disk -> Socket');
|
const diskSocket = new PairVerifierFetchable(this.personalDBGuild, this.socketGuild, 'disk-socket');
|
||||||
const ramDiskSocket = new PairVerifierFetchable(this.ramGuild, diskSocket, 'RAM -> Disk');
|
const ramDiskSocket = new PairVerifierFetchable(this.ramGuild, diskSocket, 'ram-disk');
|
||||||
|
|
||||||
// TODO: I think this unverify is causing the RARE ALERTs
|
// TODO: I think this unverify is causing the RARE ALERTs
|
||||||
// do we need to unverify on connect? or just disconnect?
|
// do we need to unverify on connect? or just disconnect?
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { AsyncFetchable, AsyncLackable, Ensurable } from './guild-types';
|
import { AsyncFetchable, AsyncLackable } from './guild-types';
|
||||||
import {
|
import {
|
||||||
Channel,
|
Channel,
|
||||||
GuildMetadata,
|
GuildMetadata,
|
||||||
@ -14,7 +14,7 @@ import PersonalDB from './personal-db';
|
|||||||
import { AutoVerifierWithArg, PartialMessageListQuery } from './auto-verifier-with-args';
|
import { AutoVerifierWithArg, PartialMessageListQuery } from './auto-verifier-with-args';
|
||||||
|
|
||||||
/** a guild connected to a local Sqlite database */
|
/** a guild connected to a local Sqlite database */
|
||||||
export default class PersonalDBGuild implements AsyncFetchable, AsyncLackable, Ensurable {
|
export default class PersonalDBGuild implements AsyncFetchable, AsyncLackable {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly db: PersonalDB,
|
private readonly db: PersonalDB,
|
||||||
private readonly guildId: number,
|
private readonly guildId: number,
|
||||||
@ -59,10 +59,6 @@ export default class PersonalDBGuild implements AsyncFetchable, AsyncLackable, E
|
|||||||
return null; // personal db currently does not handle tokens
|
return null; // personal db currently does not handle tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
async ensureVerified(): Promise<void> {
|
|
||||||
/* do nothing, we are always ready */
|
|
||||||
}
|
|
||||||
|
|
||||||
// lacking Methods (resolving differences)
|
// lacking Methods (resolving differences)
|
||||||
|
|
||||||
async handleMetadataChanged(changedMetaData: GuildMetadata): Promise<boolean> {
|
async handleMetadataChanged(changedMetaData: GuildMetadata): Promise<boolean> {
|
||||||
|
@ -7,7 +7,7 @@ const LOG = Logger.create(__filename, electronConsole);
|
|||||||
import * as socketio from 'socket.io-client';
|
import * as socketio from 'socket.io-client';
|
||||||
import { Channel, GuildMetadata, Member, Message, Resource, Token } from './data-types';
|
import { Channel, GuildMetadata, Member, Message, Resource, Token } from './data-types';
|
||||||
import Globals from './globals';
|
import Globals from './globals';
|
||||||
import { Connectable, AsyncRequestable, AsyncGuaranteedFetchable, Ensurable } from './guild-types';
|
import { Connectable, AsyncRequestable, AsyncGuaranteedFetchable } from './guild-types';
|
||||||
import DedupAwaiter from './dedup-awaiter';
|
import DedupAwaiter from './dedup-awaiter';
|
||||||
import Util from './util';
|
import Util from './util';
|
||||||
import SocketVerifier from './socket-verifier';
|
import SocketVerifier from './socket-verifier';
|
||||||
@ -17,7 +17,7 @@ import { EventEmitter } from 'tsee';
|
|||||||
/** a guild connected to a socket.io socket server */
|
/** a guild connected to a socket.io socket server */
|
||||||
export default class SocketGuild
|
export default class SocketGuild
|
||||||
extends EventEmitter<Connectable>
|
extends EventEmitter<Connectable>
|
||||||
implements AsyncGuaranteedFetchable, AsyncRequestable, Ensurable
|
implements AsyncGuaranteedFetchable, AsyncRequestable
|
||||||
{
|
{
|
||||||
private queryDedups = new Map<string, DedupAwaiter<unknown>>();
|
private queryDedups = new Map<string, DedupAwaiter<unknown>>();
|
||||||
|
|
||||||
@ -89,10 +89,6 @@ export default class SocketGuild
|
|||||||
this.socket.disconnect();
|
this.socket.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ensureVerified(): Promise<void> {
|
|
||||||
await this.verifier.ensureVerified();
|
|
||||||
}
|
|
||||||
|
|
||||||
// server helper functions
|
// server helper functions
|
||||||
|
|
||||||
private async _query(timeout: number, endpoint: string, ...args: any[]): Promise<any> {
|
private async _query(timeout: number, endpoint: string, ...args: any[]): Promise<any> {
|
||||||
|
@ -26,10 +26,6 @@ export interface AsyncFetchable {
|
|||||||
}
|
}
|
||||||
export type Fetchable = SyncFetchable | AsyncFetchable;
|
export type Fetchable = SyncFetchable | AsyncFetchable;
|
||||||
|
|
||||||
export interface Ensurable {
|
|
||||||
ensureVerified: () => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AsyncGuaranteedFetchable {
|
export interface AsyncGuaranteedFetchable {
|
||||||
fetchMetadata(): Promise<GuildMetadata>;
|
fetchMetadata(): Promise<GuildMetadata>;
|
||||||
fetchMembers(): Promise<Member[]>;
|
fetchMembers(): Promise<Member[]>;
|
||||||
|
Loading…
Reference in New Issue
Block a user