[Gekidou] Allow multiple posts in thread and posts in channel for a specific root or channel (#5594)

* Allow multiple posts in thread and posts in channel for a specific root or channel

* Apply suggestions from code review

Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com>

Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com>
This commit is contained in:
Elias Nahum 2021-08-04 15:43:25 -04:00 committed by GitHub
parent 733b10377b
commit 7c5b3a1574
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 34 additions and 12 deletions

View file

@ -52,7 +52,7 @@ export default class ChannelModel extends Model {
[GROUPS_IN_CHANNEL]: {type: 'has_many', foreignKey: 'channel_id'},
/** A CHANNEL can be associated with multiple POSTS_IN_CHANNEL (relationship is 1:N) */
[POSTS_IN_CHANNEL]: {type: 'has_many', foreignKey: 'id'},
[POSTS_IN_CHANNEL]: {type: 'has_many', foreignKey: 'channel_id'},
/** A CHANNEL can contain multiple POST (relationship is 1:N) */
[POST]: {type: 'has_many', foreignKey: 'channel_id'},

View file

@ -38,7 +38,7 @@ export default class PostModel extends Model {
[FILE]: {type: 'has_many', foreignKey: 'post_id'},
/** A POST can have multiple POSTS_IN_THREAD. (relationship is 1:N)*/
[POSTS_IN_THREAD]: {type: 'has_many', foreignKey: 'id'},
[POSTS_IN_THREAD]: {type: 'has_many', foreignKey: 'root_id'},
/** A POST can have multiple REACTION. (relationship is 1:N)*/
[REACTION]: {type: 'has_many', foreignKey: 'post_id'},

View file

@ -26,6 +26,9 @@ export default class PostsInChannelModel extends Model {
[CHANNEL]: {type: 'belongs_to', key: 'id'},
};
/** channel_id: Associated channel identifier */
@field('channel_id') channelId!: string;
/** earliest : The earliest timestamp of the post in that channel */
@field('earliest') earliest!: number;

View file

@ -26,6 +26,9 @@ export default class PostsInThreadModel extends Model {
[POST]: {type: 'belongs_to', key: 'id'},
};
/** root_id: Associated root post identifier */
@field('root_id') rootId!: string;
/** earliest : Lower bound of a timestamp range */
@field('earliest') earliest!: number;

View file

@ -75,7 +75,7 @@ const PostsInChannelHandler = (superclass: any) => class extends superclass {
// Find the records in the PostsInChannel table that have a matching channel_id
const chunks = (await this.database.get(POSTS_IN_CHANNEL).query(
Q.where('id', channelId),
Q.where('channel_id', channelId),
Q.experimentalSortBy('latest', Q.desc),
).fetch()) as PostsInChannelModel[];

View file

@ -32,13 +32,13 @@ const PostsInThreadHandler = (superclass: any) => class extends superclass {
const chunks = (await retrieveRecords({
database: this.database,
tableName: POSTS_IN_THREAD,
condition: Q.where('id', rootId),
condition: Q.where('root_id', rootId),
})) as PostsInThreadModel[];
if (chunks.length) {
const chunk = chunks[0];
const newValue = {
id: rootId,
root_id: rootId,
earliest: Math.min(chunk.earliest, firstPost.create_at),
latest: Math.max(chunk.latest, lastPost.create_at),
};
@ -50,7 +50,7 @@ const PostsInThreadHandler = (superclass: any) => class extends superclass {
} else {
// create chunk
create.push({
id: rootId,
root_id: rootId,
earliest: firstPost.create_at,
latest: lastPost.create_at,
});

View file

@ -66,7 +66,7 @@ describe('*** POST Prepare Records Test ***', () => {
record: undefined,
raw: {
id: 'ps81iqbddesfby8jayz7owg4yypoo',
post_id: '8swgtrrdiff89jnsiwiip3y1eoe',
root_id: '8swgtrrdiff89jnsiwiip3y1eoe',
earliest: 1596032651748,
latest: 1597032651748,
},

View file

@ -76,7 +76,8 @@ export const transformPostInThreadRecord = ({action, database, value}: Transform
const isCreateAction = action === OperationType.CREATE;
const fieldsMapper = (postsInThread: PostsInThreadModel) => {
postsInThread._raw.id = isCreateAction ? raw.id : record.id;
postsInThread._raw.id = isCreateAction ? (raw.id || postsInThread.id) : record.id;
postsInThread.rootId = raw.root_id;
postsInThread.earliest = raw.earliest;
postsInThread.latest = raw.latest!;
};
@ -193,7 +194,8 @@ export const transformPostsInChannelRecord = ({action, database, value}: Transfo
const isCreateAction = action === OperationType.CREATE;
const fieldsMapper = (postsInChannel: PostsInChannelModel) => {
postsInChannel._raw.id = isCreateAction ? (raw.channel_id || postsInChannel.id) : record.id;
postsInChannel._raw.id = isCreateAction ? (raw.id || postsInChannel.id) : record.id;
postsInChannel.channelId = raw.channel_id;
postsInChannel.earliest = raw.earliest;
postsInChannel.latest = raw.latest;
};

View file

@ -10,6 +10,7 @@ const {POSTS_IN_CHANNEL} = MM_TABLES.SERVER;
export default tableSchema({
name: POSTS_IN_CHANNEL,
columns: [
{name: 'channel_id', type: 'string', isIndexed: true},
{name: 'earliest', type: 'number'},
{name: 'latest', type: 'number'},
],

View file

@ -10,6 +10,7 @@ const {POSTS_IN_THREAD} = MM_TABLES.SERVER;
export default tableSchema({
name: POSTS_IN_THREAD,
columns: [
{name: 'root_id', type: 'string', isIndexed: true},
{name: 'earliest', type: 'number'},
{name: 'latest', type: 'number'},
],

View file

@ -138,10 +138,12 @@ describe('*** Test schema for SERVER database ***', () => {
[POSTS_IN_CHANNEL]: {
name: POSTS_IN_CHANNEL,
columns: {
channel_id: {name: 'channel_id', type: 'string', isIndexed: true},
earliest: {name: 'earliest', type: 'number'},
latest: {name: 'latest', type: 'number'},
},
columnArray: [
{name: 'channel_id', type: 'string', isIndexed: true},
{name: 'earliest', type: 'number'},
{name: 'latest', type: 'number'},
],
@ -189,10 +191,12 @@ describe('*** Test schema for SERVER database ***', () => {
[POSTS_IN_THREAD]: {
name: POSTS_IN_THREAD,
columns: {
root_id: {name: 'root_id', type: 'string', isIndexed: true},
earliest: {name: 'earliest', type: 'number'},
latest: {name: 'latest', type: 'number'},
},
columnArray: [
{name: 'root_id', type: 'string', isIndexed: true},
{name: 'earliest', type: 'number'},
{name: 'latest', type: 'number'},
],

View file

@ -13,7 +13,7 @@ const {SERVER: {POST, POSTS_IN_CHANNEL}} = MM_TABLES;
export const queryPostsInChannel = (database: Database, channelId: string): Promise<PostInChannelModel[]> => {
try {
return database.get(POSTS_IN_CHANNEL).query(
Q.where('id', channelId),
Q.where('channel_id', channelId),
Q.experimentalSortBy('latest', Q.desc),
).fetch() as Promise<PostInChannelModel[]>;
} catch {

View file

@ -15,6 +15,9 @@ export default class PostsInChannelModel extends Model {
/** associations : Describes every relationship to this table. */
static associations: Associations;
/** channel_id: Associated channel identifier */
channelId: string;
/** earliest : The earliest timestamp of the post in that channel */
earliest: number;

View file

@ -15,6 +15,9 @@ export default class PostsInThreadModel extends Model {
/** associations : Describes every relationship to this table. */
static associations: Associations;
/** root_id: Associated root post identifier */
rootId: string;
/** earliest : Lower bound of a timestamp range */
earliest: number;

View file

@ -37,15 +37,17 @@ type MyTeam = {
};
type PostsInChannel = {
id?: string;
channel_id: string;
earliest: number;
latest: number;
};
type PostsInThread = {
id?: string;
earliest: number;
latest?: number;
id: string;
latest: number;
root_id: string;
};
type Metadata = {