fetch messages before/after based on order

This way, if the reference message was deleted at some point, the fetch request can still go through.
Also it's easier to run the queries directly on an order id/text anyway
This commit is contained in:
Michael Peters 2022-01-23 17:23:43 -06:00
parent b97db81fa2
commit afd2939fa1
13 changed files with 86 additions and 96 deletions

View File

@ -8,7 +8,7 @@ import { Changes, WithEquals } from "./data-types";
export interface PartialMessageListQuery {
channelId: string;
messageId: string | null;
messageOrderId: string | null;
number: number;
}
@ -35,7 +35,7 @@ export class AutoVerifierWithArg<T, K> {
changesFunc: (query: PartialMessageListQuery, changesType: AutoVerifierChangesType, changes: Changes<T>) => Promise<boolean>
) {
return new AutoVerifierWithArg<T[], PartialMessageListQuery>(
query => `ch#${query.channelId} m#${query.messageId}->${query.number}`,
query => `ch#${query.channelId} mo#${query.messageOrderId}->${query.number}`,
query => primaryFunc(query),
query => trustedFunc(query),
async (query: PartialMessageListQuery, primaryResult: T[] | null, trustedResult: T[] | null) => {
@ -112,4 +112,4 @@ export class AutoVerifierWithArg<T, K> {
}
return await autoVerifier.fetchAndVerifyIfNeeded(lazyVerify);
}
}
}

View File

@ -146,7 +146,7 @@ export class Message implements WithEquals<Message> {
public channel: Channel | { id: string },
public member: Member | { id: string },
public readonly sent: Date,
public readonly _order: string, // access through order functions/methods
public readonly _order: string, // for sorting, access through order functions/methods
public readonly text: string | null,
public readonly resourceId: string | null,
public readonly resourceName: string | null,
@ -463,4 +463,4 @@ export interface ConnectionInfo {
roleName: string | null;
roleColor: string | null;
rolePriority: number | null;
}
}

View File

@ -814,11 +814,11 @@ export function useMessagesScrollingSubscription(guild: CombinedGuild, channel:
}, [ guild, channelGuild, channel.id, maxFetchElements ]);
const fetchAboveFunc = useCallback(async (reference: Message) => {
if (guild !== channelGuild) return [];
return await guild.fetchMessagesBefore(channel.id, reference.id, maxFetchElements);
return await guild.fetchMessagesBefore(channel.id, reference._order, maxFetchElements);
}, [ guild, channelGuild, channel.id, maxFetchElements ]);
const fetchBelowFunc = useCallback(async (reference: Message) => {
if (guild !== channelGuild) return [];
return await guild.fetchMessagesAfter(channel.id, reference.id, maxFetchElements);
return await guild.fetchMessagesAfter(channel.id, reference._order, maxFetchElements);
}, [ guild, channelGuild, channel.id, maxFetchElements ]);
return useMultipleGuildSubscriptionScrolling(
guild, {

View File

@ -23,11 +23,11 @@ export default class EnsuredFetchable implements GuaranteedFetchable {
async fetchMessagesRecent(channelId: string, number: number): Promise<Message[]> {
return EnsuredFetchable.guarantee(await this.fetchable.fetchMessagesRecent(channelId, number));
}
async fetchMessagesBefore(channelId: string, messageId: string, number: number): Promise<Message[]> {
return EnsuredFetchable.guarantee(await this.fetchable.fetchMessagesBefore(channelId, messageId, number));
async fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Promise<Message[]> {
return EnsuredFetchable.guarantee(await this.fetchable.fetchMessagesBefore(channelId, messageOrderId, number));
}
async fetchMessagesAfter(channelId: string, messageId: string, number: number): Promise<Message[]> {
return EnsuredFetchable.guarantee(await this.fetchable.fetchMessagesAfter(channelId, messageId, number));
async fetchMessagesAfter(channelId: string, messageOrderId: string, number: number): Promise<Message[]> {
return EnsuredFetchable.guarantee(await this.fetchable.fetchMessagesAfter(channelId, messageOrderId, number));
}
async fetchResource(resourceId: string): Promise<Resource> {
return EnsuredFetchable.guarantee(await this.fetchable.fetchResource(resourceId));

View File

@ -77,14 +77,14 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
);
this.fetchMessagesBeforeVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
async (query: PartialMessageListQuery) => await this.primary.fetchMessagesBefore(query.channelId, query.messageId as string, query.number),
async (query: PartialMessageListQuery) => await this.trusted.fetchMessagesBefore(query.channelId, query.messageId as string, query.number),
async (query: PartialMessageListQuery) => await this.primary.fetchMessagesBefore(query.channelId, query.messageOrderId as string, query.number),
async (query: PartialMessageListQuery) => await this.trusted.fetchMessagesBefore(query.channelId, query.messageOrderId as string, query.number),
this.handleMessagesConflict.bind(this)
);
this.fetchMessagesAfterVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
async (query: PartialMessageListQuery) => await this.primary.fetchMessagesAfter(query.channelId, query.messageId as string, query.number),
async (query: PartialMessageListQuery) => await this.trusted.fetchMessagesAfter(query.channelId, query.messageId as string, query.number),
async (query: PartialMessageListQuery) => await this.primary.fetchMessagesAfter(query.channelId, query.messageOrderId as string, query.number),
async (query: PartialMessageListQuery) => await this.trusted.fetchMessagesAfter(query.channelId, query.messageOrderId as string, query.number),
this.handleMessagesConflict.bind(this)
);
}
@ -195,13 +195,13 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
return await this.fetchChannelsVerifier.fetchAndVerifyIfNeeded();
}
async fetchMessagesRecent(channelId: string, number: number): Promise<Message[] | null> {
return await this.fetchMessagesRecentVerifier.fetchAndVerifyIfNeded({ channelId, messageId: null, number });
return await this.fetchMessagesRecentVerifier.fetchAndVerifyIfNeded({ channelId, messageOrderId: null, number });
}
async fetchMessagesBefore(channelId: string, messageId: string, number: number): Promise<Message[] | null> {
return await this.fetchMessagesBeforeVerifier.fetchAndVerifyIfNeded({ channelId, messageId, number });
async fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Promise<Message[] | null> {
return await this.fetchMessagesBeforeVerifier.fetchAndVerifyIfNeded({ channelId, messageOrderId, number });
}
async fetchMessagesAfter(channelId: string, messageId: string, number: number): Promise<Message[] | null> {
return await this.fetchMessagesAfterVerifier.fetchAndVerifyIfNeded({ channelId, messageId, number });
async fetchMessagesAfter(channelId: string, messageOrderId: string, number: number): Promise<Message[] | null> {
return await this.fetchMessagesAfterVerifier.fetchAndVerifyIfNeded({ channelId, messageOrderId, number });
}
async fetchResource(resourceId: string): Promise<Resource | null> {
return await this.fetchResourceVerifier.fetchAndVerifyIfNeded({ id: resourceId }, true); // lazy verification

View File

@ -353,19 +353,19 @@ export default class CombinedGuild extends EventEmitter<Connectable & Conflictab
}
return messages;
}
async fetchMessagesBefore(channelId: string, messageId: string, number: number): Promise<Message[]> {
async fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Promise<Message[]> {
const members = await this.grabRAMMembersMap();
const channels = await this.grabRAMChannelsMap();
const messages = await this.fetchable.fetchMessagesBefore(channelId, messageId, number);
const messages = await this.fetchable.fetchMessagesBefore(channelId, messageOrderId, number);
for (const message of messages) {
message.fill(members, channels);
}
return messages;
}
async fetchMessagesAfter(channelId: string, messageId: string, number: number): Promise<Message[]> {
async fetchMessagesAfter(channelId: string, messageOrderId: string, number: number): Promise<Message[]> {
const members = await this.grabRAMMembersMap();
const channels = await this.grabRAMChannelsMap();
const messages = await this.fetchable.fetchMessagesAfter(channelId, messageId, number);
const messages = await this.fetchable.fetchMessagesAfter(channelId, messageOrderId, number);
for (const message of messages) {
message.fill(members, channels);
}

View File

@ -1,8 +1,3 @@
import * as electronRemote from '@electron/remote';
const electronConsole = electronRemote.getGlobal('console') as Console;
import Logger from '../../logger/logger';
const LOG = Logger.create(__filename, electronConsole);
import { AsyncFetchable, AsyncLackable } from "./guild-types";
import { Channel, GuildMetadata, GuildMetadataLocal, Member, Message, Resource, SocketConfig, Token } from "./data-types";
@ -13,7 +8,7 @@ export default class PersonalDBGuild implements AsyncFetchable, AsyncLackable {
constructor(
private readonly db: PersonalDB,
private readonly guildId: number,
private readonly memberId: string, // would be used if we want to cache-update the status/display name of members
/*private */readonly _memberId: string, // would be used if we want to cache-update the status/display name of members
) {}
// Fetched Methods
@ -38,12 +33,12 @@ export default class PersonalDBGuild implements AsyncFetchable, AsyncLackable {
return await this.db.fetchMessagesRecent(this.guildId, channelId, number);
}
async fetchMessagesBefore(channelId: string, messageId: string, number: number): Promise<Message[] | null> {
return await this.db.fetchMessagesBefore(this.guildId, channelId, messageId, number);
async fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Promise<Message[] | null> {
return await this.db.fetchMessagesBefore(this.guildId, channelId, messageOrderId, number);
}
async fetchMessagesAfter(channelId: string, messageId: string, number: number): Promise<Message[] | null> {
return await this.db.fetchMessagesAfter(this.guildId, channelId, messageId, number);
async fetchMessagesAfter(channelId: string, messageOrderId: string, number: number): Promise<Message[] | null> {
return await this.db.fetchMessagesAfter(this.guildId, channelId, messageOrderId, number);
}
async fetchResource(resourceId: string): Promise<Resource | null> {
@ -97,9 +92,9 @@ export default class PersonalDBGuild implements AsyncFetchable, AsyncLackable {
async handleMessagesAdded(
addedMessages: Message[],
recentAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
_recentAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
_beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
_afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
): Promise<boolean> {
// The PersonalDB does not remove old messages (yet) so nothing here would unverify
//LOG.debug(addedMessages.length + ' personal messages added');
@ -108,9 +103,9 @@ export default class PersonalDBGuild implements AsyncFetchable, AsyncLackable {
}
async handleMessagesChanged(
changedMessages: Message[],
recentAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
_recentAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
_beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
_afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
): Promise<boolean> {
// The PersonalDB does not remove old messages (yet) so nothing here would unverify
//LOG.debug(changedMessages.length + ' personal messages changed');
@ -119,9 +114,9 @@ export default class PersonalDBGuild implements AsyncFetchable, AsyncLackable {
}
async handleMessagesDeleted(
deletedMessages: Message[],
recentAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
_recentAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
_beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
_afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
): Promise<boolean> {
// The PersonalDB does not remove old messages (yet) so nothing here would unverify
//LOG.debug(deletedMessages.length + ' personal messages deleted');
@ -145,13 +140,13 @@ export default class PersonalDBGuild implements AsyncFetchable, AsyncLackable {
return true;
}
async handleTokensAdded(addedTokens: Token[]): Promise<boolean> {
async handleTokensAdded(_addedTokens: Token[]): Promise<boolean> {
return false; // cache currently does not handle tokens
}
async handleTokensChanged(changedTokens: Token[]): Promise<boolean> {
async handleTokensChanged(_changedTokens: Token[]): Promise<boolean> {
return false; // cache currently does not handle tokens
}
async handleTokensDeleted(deletedTokens: Token[]): Promise<boolean> {
async handleTokensDeleted(_deletedTokens: Token[]): Promise<boolean> {
return false; // cache currently does not handle tokens
}
}

View File

@ -1,8 +1,3 @@
import * as electronRemote from '@electron/remote';
const electronConsole = electronRemote.getGlobal('console') as Console;
import Logger from '../../logger/logger';
const LOG = Logger.create(__filename, electronConsole);
import { SyncFetchable, SyncLackable } from "./guild-types";
import { GuildMetadata, Member, Channel, Message, Resource, Token } from "./data-types";
import MessageRAMCache from "./message-ram-cache";
@ -39,10 +34,10 @@ export default class RAMGuild implements SyncFetchable, SyncLackable {
fetchMessagesRecent(channelId: string, number: number): Message[] | null {
return this.recentMessages.fetchRecentMessages(this.guildId, channelId, number);
}
fetchMessagesBefore(channelId: string, messageId: string, number: number): Message[] | null {
fetchMessagesBefore(_channelId: string, _messageOrderId: string, _number: number): Message[] | null {
return null; // not planning on doing this unless someone wants to do a scrolling cache
}
fetchMessagesAfter(channelId: string, messageId: string, number: number): Message[] | null {
fetchMessagesAfter(_channelId: string, _messageOrderId: string, _number: number): Message[] | null {
return null; // not planning on doing this unless someone wants to do a scrolling cache
}
fetchResource(resourceId: string): Resource | null {
@ -101,8 +96,8 @@ export default class RAMGuild implements SyncFetchable, SyncLackable {
handleMessagesAdded(
addedMessages: Message[],
recentAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
_beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
_afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
): boolean {
const byChannel = new Map<string, Message[]>();
for (const message of addedMessages) {
@ -120,8 +115,8 @@ export default class RAMGuild implements SyncFetchable, SyncLackable {
handleMessagesChanged(
changedMessages: Message[],
recentAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
_beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
_afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
): boolean {
const byChannel = new Map<string, Message[]>();
for (const message of changedMessages) {
@ -139,8 +134,8 @@ export default class RAMGuild implements SyncFetchable, SyncLackable {
handleMessagesDeleted(
deletedMessages: Message[],
recentAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
_beforeAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>,
_afterAutoVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>
): boolean {
const byChannel = new Map<string, Message[]>();
for (const message of deletedMessages) {
@ -165,19 +160,19 @@ export default class RAMGuild implements SyncFetchable, SyncLackable {
this.resources.putResource(this.guildId, changedResource);
return true;
}
handleResourceDeleted(deletedResource: Resource): boolean {
handleResourceDeleted(_deletedResource: Resource): boolean {
// do nothing, the cache will garbage collect itself and this is probably fine to leave as verified :)
// also resource deletion should be pretty rare, especially in a cache
return true;
}
handleTokensAdded(addedTokens: Token[]): boolean {
handleTokensAdded(_addedTokens: Token[]): boolean {
return false; // TODO: token ram cache
}
handleTokensChanged(changedTokens: Token[]): boolean {
handleTokensChanged(_changedTokens: Token[]): boolean {
return false; // TODO: token ram cache
}
handleTokensDeleted(deletedTokens: Token[]): boolean {
handleTokensDeleted(_deletedTokens: Token[]): boolean {
return false; // TODO: token ram cache
}
}
}

View File

@ -146,12 +146,12 @@ export default class SocketGuild extends EventEmitter<Connectable> implements As
const data = await this.queryOnceVerifiedDedup(Globals.DEFAULT_SOCKET_TIMEOUT, 'fetch-messages-recent', channelId, number);
return data.map((dataMessage: any) => Message.fromDBData(dataMessage));
}
async fetchMessagesBefore(channelId: string, messageId: string, number: number): Promise<Message[]> {
const data = await this.queryOnceVerifiedDedup(Globals.DEFAULT_SOCKET_TIMEOUT, 'fetch-messages-before', channelId, messageId, number);
async fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Promise<Message[]> {
const data = await this.queryOnceVerifiedDedup(Globals.DEFAULT_SOCKET_TIMEOUT, 'fetch-messages-before', channelId, messageOrderId, number);
return data.map((dataMessage: any) => Message.fromDBData(dataMessage));
}
async fetchMessagesAfter(channelId: string, messageId: string, number: number): Promise<Message[]> {
const data = await this.queryOnceVerifiedDedup(Globals.DEFAULT_SOCKET_TIMEOUT, 'fetch-messages-after', channelId, messageId, number);
async fetchMessagesAfter(channelId: string, messageOrderId: string, number: number): Promise<Message[]> {
const data = await this.queryOnceVerifiedDedup(Globals.DEFAULT_SOCKET_TIMEOUT, 'fetch-messages-after', channelId, messageOrderId, number);
return data.map((dataMessage: any) => Message.fromDBData(dataMessage));
}
async fetchResource(resourceId: string): Promise<Resource> {
@ -165,10 +165,10 @@ export default class SocketGuild extends EventEmitter<Connectable> implements As
// We don't want to dedup these
async requestSendMessage(channelId: string, text: string): Promise<void> {
const _dataMessage = await this.queryOnceVerified(Globals.DEFAULT_SOCKET_TIMEOUT, 'send-message', channelId, text);
/*const _dataMessage = */await this.queryOnceVerified(Globals.DEFAULT_SOCKET_TIMEOUT, 'send-message', channelId, text);
}
async requestSendMessageWithResource(channelId: string, text: string | null, resource: Buffer, resourceName: string): Promise<void> {
const _dataMessage = await this.queryOnceVerified(Globals.DEFAULT_SOCKET_TIMEOUT, 'send-message-with-resource', channelId, text, resource, resourceName);
/*const _dataMessage = */await this.queryOnceVerified(Globals.DEFAULT_SOCKET_TIMEOUT, 'send-message-with-resource', channelId, text, resource, resourceName);
}
async requestSetStatus(status: string): Promise<void> {
await this.queryOnceVerified(Globals.DEFAULT_SOCKET_TIMEOUT, 'set-status', status);

View File

@ -9,8 +9,8 @@ export interface SyncFetchable {
fetchMembers(): Member[] | null;
fetchChannels(): Channel[] | null;
fetchMessagesRecent(channelId: string, number: number): Message[] | null;
fetchMessagesBefore(channelId: string, messageId: string, number: number): Message[] | null;
fetchMessagesAfter(channelId: string, messageId: string, number: number): Message[] | null;
fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Message[] | null;
fetchMessagesAfter(channelId: string, messageOrderId: string, number: number): Message[] | null;
fetchResource(resourceId: string): Resource | null;
fetchTokens(): Token[] | null;
}
@ -19,8 +19,8 @@ export interface AsyncFetchable {
fetchMembers(): Promise<Member[] | null>;
fetchChannels(): Promise<Channel[] | null>;
fetchMessagesRecent(channelId: string, number: number): Promise<Message[] | null>;
fetchMessagesBefore(channelId: string, messageId: string, number: number): Promise<Message[] | null>;
fetchMessagesAfter(channelId: string, messageId: string, number: number): Promise<Message[] | null>;
fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Promise<Message[] | null>;
fetchMessagesAfter(channelId: string, messageOrderId: string, number: number): Promise<Message[] | null>;
fetchResource(resourceId: string): Promise<Resource | null>;
fetchTokens(): Promise<Token[] | null>;
}
@ -31,8 +31,8 @@ export interface AsyncGuaranteedFetchable {
fetchMembers(): Promise<Member[]>;
fetchChannels(): Promise<Channel[]>;
fetchMessagesRecent(channelId: string, number: number): Promise<Message[]>;
fetchMessagesBefore(channelId: string, messageId: string, number: number): Promise<Message[]>;
fetchMessagesAfter(channelId: string, messageId: string, number: number): Promise<Message[]>;
fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Promise<Message[]>;
fetchMessagesAfter(channelId: string, messageOrderId: string, number: number): Promise<Message[]>;
fetchResource(resourceId: string): Promise<Resource>;
fetchTokens(): Promise<Token[]>;
}

View File

@ -522,7 +522,7 @@ export default class PersonalDB {
return messages.map(dataMessage => Message.fromDBData(dataMessage));
}
async fetchMessagesBefore(guildId: number, channelId: string, messageId: string, number: number): Promise<Message[] | null> {
async fetchMessagesBefore(guildId: number, channelId: string, messageOrderId: string, number: number): Promise<Message[] | null> {
const messages = await this.db.all(`
SELECT * FROM (
SELECT *
@ -530,26 +530,26 @@ export default class PersonalDB {
WHERE
"guild_id"=:guild_id
AND "channel_id"=:channel_id
AND "order" < (SELECT "order" FROM "messages" WHERE "id"=:message_id)
AND "order" < :order
ORDER BY "order" DESC, "id" DESC
LIMIT :number
) AS "r" ORDER BY "r"."order" ASC
`, { ':guild_id': guildId, ':channel_id': channelId, ':message_id': messageId, ':number': number });
`, { ':guild_id': guildId, ':channel_id': channelId, ':order': messageOrderId, ':number': number });
if (messages.length === 0) return null;
return messages.map(dataMessage => Message.fromDBData(dataMessage));
}
async fetchMessagesAfter(guildId: number, channelId: string, messageId: string, number: number): Promise<Message[] | null> {
async fetchMessagesAfter(guildId: number, channelId: string, messageOrderId: string, number: number): Promise<Message[] | null> {
const messages = await this.db.all(`
SELECT *
FROM "messages"
WHERE
"guild_id"=:guild_id
AND "channel_id"=:channel_id
AND "order" > (SELECT "order" FROM "messages" WHERE "id"=:message_id)
AND "order" > :order
ORDER BY "order" ASC
LIMIT :number
`, { ':guild_id': guildId, ':channel_id': channelId, ':message_id': messageId, ':number': number });
`, { ':guild_id': guildId, ':channel_id': channelId, ':order': messageOrderId, ':number': number });
if (messages.length === 0) return null;
return messages.map(dataMessage => Message.fromDBData(dataMessage));
}

View File

@ -173,7 +173,7 @@ export default class DB {
return result.rows;
}
static async getMessagesBefore(guildId: string, channelId: string, messageId: string, number: number): Promise<any[]> {
static async getMessagesBefore(guildId: string, channelId: string, messageOrderId: string, number: number): Promise<any[]> {
const result = await db.query(`
SELECT * FROM (
SELECT
@ -189,14 +189,14 @@ export default class DB {
WHERE
"guild_id"=$1
AND "channel_id"=$2
AND "order" < (SELECT "order" FROM "messages" WHERE "id"=$3)
AND "order" < $3
ORDER BY "order" DESC
LIMIT $4
) AS "r" ORDER BY "r"."order" ASC`, [ guildId, channelId, messageId, number ]);
) AS "r" ORDER BY "r"."order" ASC`, [ guildId, channelId, messageOrderId, number ]);
return result.rows;
}
static async getMessagesAfter(guildId: string, channelId: string, messageId: string, number: number): Promise<any[]> {
static async getMessagesAfter(guildId: string, channelId: string, messageOrderId: string, number: number): Promise<any[]> {
const result = await db.query(`
SELECT
"id", "channel_id", "member_id"
@ -211,9 +211,9 @@ export default class DB {
WHERE
"guild_id"=$1
AND "channel_id"=$2
AND "order" > (SELECT "order" FROM "messages" WHERE "id"=$3)
AND "order" > $3
ORDER BY "order" ASC, "id" ASC
LIMIT $4`, [ guildId, channelId, messageId, number ]);
LIMIT $4`, [ guildId, channelId, messageOrderId, number ]);
return result.rows;
}

View File

@ -778,7 +778,7 @@ function bindFetchEvents(client: socketio.Socket, identity: IIdentity): void { /
* client.on('fetch-messages-before', (channelId, messageId, number, respond(errStr, messages)))
* Fetch messages coming before the specified message
* @param channelId The channel uuid of the channel
* @param messageId The id of the base message (will not be included in results)
* @param messageOrderId The order string of the base message (will not be included in results)
* @param number The maximum number of messages to get
* @param respond function(errStr, messages) as a socket.io response function
* @param respond.errStr Error string if an error, else null
@ -788,11 +788,11 @@ function bindFetchEvents(client: socketio.Socket, identity: IIdentity): void { /
client, identity,
{ verified: true },
'fetch-messages-before', [ 'string', 'string', 'number', 'function' ],
async (channelId, messageId, number, respond) => {
async (channelId, messageOrderId, number, respond) => {
if (!identity.guildId) throw new EventError('identity no guildId');
if (!identity.memberId) throw new EventError('identity no memberId');
LOG.info(`u#${identity.memberId}: fetching messages before ch#${channelId} m#${messageId} number: ${number}`);
const messages = await DB.getMessagesBefore(identity.guildId, channelId, messageId, number);
LOG.info(`u#${identity.memberId}: fetching messages before ch#${channelId} mo#${messageOrderId} number: ${number}`);
const messages = await DB.getMessagesBefore(identity.guildId, channelId, messageOrderId, number);
respond(null, messages);
}
);
@ -800,7 +800,7 @@ function bindFetchEvents(client: socketio.Socket, identity: IIdentity): void { /
/*
* Fetch messages coming after the specified message
* @param channelId The channel uuid of the channel
* @param messageId The id of the base message (will not be included in results)
* @param messageOrderId The order string of the base message (will not be included in results)
* @param number The maximum number of messages to get
* @param respond function(errStr, messages) as a socket.io response function
* @param respond.errStr Error string if an error, else null
@ -810,11 +810,11 @@ function bindFetchEvents(client: socketio.Socket, identity: IIdentity): void { /
client, identity,
{ verified: true },
'fetch-messages-after', [ 'string', 'string', 'number', 'function' ],
async (channelId, messageId, number, respond) => {
async (channelId, messageOrderId, number, respond) => {
if (!identity.guildId) throw new EventError('identity no guildId');
if (!identity.memberId) throw new EventError('identity no memberId');
LOG.info(`u#${identity.memberId}: fetching messages after ch#${channelId} m#${messageId} number: ${number}`);
const messages = await DB.getMessagesAfter(identity.guildId, channelId, messageId, number);
LOG.info(`u#${identity.memberId}: fetching messages after ch#${channelId} mo#${messageOrderId} number: ${number}`);
const messages = await DB.getMessagesAfter(identity.guildId, channelId, messageOrderId, number);
respond(null, messages);
}
);