refactor discourse createGraph (#1409)
This is a minor refactor to re-organize the createGraph function in the Discourse plugin to use a class under the hood. Using a hidden class makes sense because there is a fair bit of shared state that's needed while creating the graph. The proximate cause for this refactor is tha adding reference edges will bloat the `addPost` section of the function, which was already a little too complex. Simply shoving in more complexity would make it unweidy. So I opted for this minor refactor. It's internal-only (no public APIs are changed). Test plan: `yarn test` passes. As noted, refactor is internal-only. This is progress towards [Discourse reference and mention detection][1]. [1]: https://discourse.sourcecred.io/t/discourse-reference-mention-detection/270
This commit is contained in:
parent
d4804a7a68
commit
e1a73ac368
|
@ -128,27 +128,59 @@ export function likesEdge(serverUrl: string, like: LikeAction): Edge {
|
|||
}
|
||||
|
||||
export function createGraph(serverUrl: string, data: DiscourseData): Graph {
|
||||
const gc = new _GraphCreator(serverUrl, data);
|
||||
return gc.graph;
|
||||
}
|
||||
|
||||
class _GraphCreator {
|
||||
graph: Graph;
|
||||
serverUrl: string;
|
||||
data: DiscourseData;
|
||||
topicIdToTitle: Map<TopicId, string>;
|
||||
|
||||
constructor(serverUrl: string, data: DiscourseData) {
|
||||
if (serverUrl.endsWith("/")) {
|
||||
throw new Error(`by convention, serverUrl should not end with /`);
|
||||
}
|
||||
const g = new Graph();
|
||||
const topicIdToTitle: Map<TopicId, string> = new Map();
|
||||
this.serverUrl = serverUrl;
|
||||
this.data = data;
|
||||
this.graph = new Graph();
|
||||
this.topicIdToTitle = new Map();
|
||||
|
||||
for (const username of data.users()) {
|
||||
g.addNode(userNode(serverUrl, username));
|
||||
this.graph.addNode(userNode(serverUrl, username));
|
||||
}
|
||||
|
||||
for (const topic of data.topics()) {
|
||||
topicIdToTitle.set(topic.id, topic.title);
|
||||
g.addNode(topicNode(serverUrl, topic));
|
||||
g.addEdge(authorsTopicEdge(serverUrl, topic));
|
||||
this.topicIdToTitle.set(topic.id, topic.title);
|
||||
this.graph.addNode(topicNode(serverUrl, topic));
|
||||
this.graph.addEdge(authorsTopicEdge(serverUrl, topic));
|
||||
}
|
||||
|
||||
for (const post of data.posts()) {
|
||||
const topicTitle = topicIdToTitle.get(post.topicId) || "[unknown topic]";
|
||||
g.addNode(postNode(serverUrl, post, topicTitle));
|
||||
g.addEdge(authorsPostEdge(serverUrl, post));
|
||||
g.addEdge(topicContainsPostEdge(serverUrl, post));
|
||||
this.addPost(post);
|
||||
}
|
||||
|
||||
for (const like of data.likes()) {
|
||||
this.graph.addEdge(likesEdge(serverUrl, like));
|
||||
}
|
||||
}
|
||||
|
||||
addPost(post: Post) {
|
||||
const topicTitle =
|
||||
this.topicIdToTitle.get(post.topicId) || "[unknown topic]";
|
||||
this.graph.addNode(postNode(this.serverUrl, post, topicTitle));
|
||||
this.graph.addEdge(authorsPostEdge(this.serverUrl, post));
|
||||
this.graph.addEdge(topicContainsPostEdge(this.serverUrl, post));
|
||||
this.maybeAddPostRepliesEdge(post);
|
||||
}
|
||||
|
||||
/**
|
||||
* Any post that is not the first post in the thread is a reply to some post.
|
||||
* This method adds those reply edges. It is a bit hairy to work around unintuitive
|
||||
* choices in the Discourse API.
|
||||
*/
|
||||
maybeAddPostRepliesEdge(post: Post) {
|
||||
let replyToPostIndex = post.replyToPostIndex;
|
||||
if (replyToPostIndex == null && post.indexWithinTopic > 1) {
|
||||
// For posts that are a reply to the first posts (or, depending on how you look at it,
|
||||
|
@ -158,16 +190,13 @@ export function createGraph(serverUrl: string, data: DiscourseData): Graph {
|
|||
replyToPostIndex = 1;
|
||||
}
|
||||
if (replyToPostIndex != null) {
|
||||
const basePostId = data.findPostInTopic(post.topicId, replyToPostIndex);
|
||||
const basePostId = this.data.findPostInTopic(
|
||||
post.topicId,
|
||||
replyToPostIndex
|
||||
);
|
||||
if (basePostId != null) {
|
||||
g.addEdge(postRepliesEdge(serverUrl, post, basePostId));
|
||||
this.graph.addEdge(postRepliesEdge(this.serverUrl, post, basePostId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const like of data.likes()) {
|
||||
g.addEdge(likesEdge(serverUrl, like));
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue