Discourse: add categoryId and bumpedMs to Topic data (#1454)

As not all API calls return bumpedMs, make a new type
to show the distinction.
This commit is contained in:
Robin van Boven 2019-11-16 13:52:32 +01:00 committed by GitHub
parent e79cca6c6c
commit 23f1db6ce4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 20 deletions

View File

@ -47,6 +47,7 @@ Object {
],
"topic": Object {
"authorUsername": "d11",
"categoryId": 1,
"id": 11,
"timestampMs": 1564744349408,
"title": "My First Test Post",

View File

@ -84,6 +84,8 @@ describe("plugins/discourse/createGraph", () => {
title: "first topic",
timestampMs: 0,
authorUsername: "decentralion",
categoryId: 1,
bumpedMs: 0,
};
const post1 = {
id: 1,

View File

@ -20,13 +20,29 @@ export type PostId = number;
export type TopicId = number;
export type CategoryId = number;
export type Topic = {|
/**
* The "view" received from the Discourse API
* when getting a topic by ID.
*
* This filters some relevant data like bumpedMs,
* and the type separation makes this distinction clear.
*/
export type TopicView = {|
+id: TopicId,
+categoryId: CategoryId,
+title: string,
+timestampMs: number,
+authorUsername: string,
|};
/**
* A complete Topic object.
*/
export type Topic = {|
...TopicView,
+bumpedMs: number,
|};
export type Post = {|
+id: PostId,
+topicId: TopicId,
@ -43,7 +59,7 @@ export type Post = {|
|};
export type TopicWithPosts = {|
+topic: Topic,
+topic: TopicView,
// Not guaranteed to contain all the Posts in the topic—clients will need to
// manually request some posts. The raw response actually includes a list of
// all the PostIds in the topic, but for now we don't use them.
@ -182,11 +198,12 @@ export class Fetcher implements Discourse {
}
failForNotOk(response);
const json = await response.json();
const posts = json.post_stream.posts.map(parsePost);
const topic: Topic = {
let posts = json.post_stream.posts.map(parsePost);
const topic: TopicView = {
id: json.id,
categoryId: json.category_id,
title: json.title,
timestampMs: +new Date(json.created_at),
timestampMs: Date.parse(json.created_at),
authorUsername: json.details.created_by.username,
};
return {topic, posts};

View File

@ -1,7 +1,7 @@
// @flow
import type {TaskReporter} from "../../util/taskReporter";
import type {Discourse, CategoryId} from "./fetch";
import type {Discourse, CategoryId, Topic} from "./fetch";
import {MirrorRepository} from "./mirrorRepository";
export type MirrorOptions = {|
@ -117,7 +117,10 @@ export class Mirror {
const topicWithPosts = await this._fetcher.topicWithPosts(topicId);
if (topicWithPosts != null) {
const {topic, posts} = topicWithPosts;
this._repo.addTopic(topic);
// TODO: Quick hack, as TopicView does not include bumpedMs.
// This should be resolved in the new sync logic.
const workaroundTopic: Topic = {...topic, bumpedMs: topic.timestampMs};
this._repo.addTopic(workaroundTopic);
for (const post of posts) {
addPost(post);
}

View File

@ -9,6 +9,7 @@ import {
type TopicId,
type PostId,
type Topic,
type TopicView,
type Post,
type TopicWithPosts,
type LikeAction,
@ -64,7 +65,7 @@ class MockFetcher implements Discourse {
// Only return the first post in the posts array, to ensure that we have to
// test the functionality where we manually grab posts by ID
const posts = [firstPost];
return {topic: this._topic(id), posts};
return {topic: this._topicView(id), posts};
}
async likesByUser(
@ -79,8 +80,16 @@ class MockFetcher implements Discourse {
}
_topic(id: TopicId): Topic {
return {
...this._topicView(id),
bumpedMs: 1000,
};
}
_topicView(id: TopicId): TopicView {
return {
id,
categoryId: 1,
title: `topic ${id}`,
timestampMs: 1000,
authorUsername: "credbot",

View File

@ -3,17 +3,11 @@
import type {Database} from "better-sqlite3";
import stringify from "json-stable-stringify";
import dedent from "../../util/dedent";
import {
type TopicId,
type PostId,
type Topic,
type Post,
type LikeAction,
} from "./fetch";
import type {TopicId, PostId, Topic, Post, LikeAction} from "./fetch";
// The version should be bumped any time the database schema is changed,
// so that the cache will be properly invalidated.
const VERSION = "discourse_mirror_v4";
const VERSION = "discourse_mirror_v5";
/**
* An interface for reading the local Discourse data.
@ -142,8 +136,10 @@ export class SqliteMirrorRepository
dedent`\
CREATE TABLE topics (
id INTEGER PRIMARY KEY,
category_id INTEGER NOT NULL,
title TEXT NOT NULL,
timestamp_ms INTEGER NOT NULL,
bumped_ms INTEGER NOT NULL,
author_username TEXT NOT NULL,
FOREIGN KEY(author_username) REFERENCES users(username)
)
@ -198,17 +194,21 @@ export class SqliteMirrorRepository
dedent`\
SELECT
id,
category_id,
title,
timestamp_ms,
author_username,
title
bumped_ms,
author_username
FROM topics`
)
.all()
.map((x) => ({
id: x.id,
timestampMs: x.timestamp_ms,
authorUsername: x.author_username,
categoryId: x.category_id,
title: x.title,
timestampMs: x.timestamp_ms,
bumpedMs: x.bumped_ms,
authorUsername: x.author_username,
}));
}
@ -336,21 +336,27 @@ export class SqliteMirrorRepository
dedent`\
REPLACE INTO topics (
id,
category_id,
title,
timestamp_ms,
bumped_ms,
author_username
) VALUES (
:id,
:category_id,
:title,
:timestamp_ms,
:bumped_ms,
:author_username
)
`
)
.run({
id: topic.id,
category_id: topic.categoryId,
title: topic.title,
timestamp_ms: topic.timestampMs,
bumped_ms: topic.bumpedMs,
author_username: topic.authorUsername,
});
return toAddResult(res);