Skip to content

Commit

Permalink
Fix Manual Syncing Tool - (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisjtang authored Jan 9, 2024
1 parent 4ca310a commit 18d3cf1
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 29 deletions.
11 changes: 3 additions & 8 deletions disqus/rest-api/class-disqus-rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,6 @@ private function update_comment_from_post( $post, $comments ) {
// Remove non-updating fields.
unset( $comment_data['comment_meta'] );
unset( $comment_data['comment_agent'] );
unset( $comment_data['comment_parent'] );
unset( $comment_data['comment_type'] );
unset( $comment_data['comment_date_gmt'] );
unset( $comment_data['comment_post_ID'] );
Expand Down Expand Up @@ -763,11 +762,9 @@ private function comment_data_from_post( $post ) {
update_post_meta( $wp_post_id, 'dsq_thread_id', $thread['id'] );
}

if ( null === $wp_post_id || false == $wp_post_id ) {
throw new Exception( 'No post found associated with the thread.' );
}

// Find the parent comment, if any.
// To simplify our syncing process and prevent syncing errors,
// still sync the comment even if we don't have its parent comment synced.
$parent = 0;
if ( null !== $post['parent'] ) {
$parent_comment_query = new WP_Comment_Query( array(
Expand All @@ -777,9 +774,7 @@ private function comment_data_from_post( $post ) {
) );
$parent_comments = $parent_comment_query->comments;

if ( empty( $parent_comments ) ) {
throw new Exception( 'This comment\'s parent has not been synced yet.' );
} else {
if ( $parent_comments ) {
$parent = $parent_comments[0]->comment_ID;
}
}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/ts/DisqusApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class DisqusApi {
`end=${endDate.toISOString()}`,
`forum=${this.forum}`,
'related=thread',
'order=asc',
`limit=${Math.min(Math.max(limit, 1), 100)}`,
`cursor=${cursor || ''}`,
].join('&');
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/WordPressRestApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export class WordPressRestApi {
status: XHR.status,
statusText: XHR.statusText
});
console.error('Error', XHR.statusText);
console.error('Error Status: ', XHR.statusText, '100 character server response preview: ', XHR.responseText.substring(0, 100));
}
};
XHR.send(data);
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/ts/components/ManualSyncForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const ManualSyncForm = (props: IFormProps) => {
>
<h4>{__('Manually Sync Comments')}</h4>
<p className='description'>
{__('Select a time range to sync past comments. Date ranges are limited to a maximum of 12 months.')}
{__('Select a time range to sync past comments. Date ranges can go up to a maximum of 5 years.')}
</p>
<table className='form-table'>
<tbody>
Expand All @@ -30,7 +30,7 @@ const ManualSyncForm = (props: IFormProps) => {
value={props.data.manualSyncRangeStart}
onChange={props.onDateSelectorInputchange.bind(null, 'manualSyncRangeStart')}
max={props.data.manualSyncRangeEnd}
min={moment(props.data.manualSyncRangeEnd).subtract(12, 'months').format('YYYY-MM-DD')}
min={moment(props.data.manualSyncRangeEnd).subtract(60, 'months').format('YYYY-MM-DD')}
disabled={props.data.isManualSyncRunning}
/>
<p className='description'>
Expand Down
50 changes: 32 additions & 18 deletions frontend/src/ts/containers/mapDispatchToProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,11 @@ const valueFromInput = (element: HTMLInputElement): string => {
let syncedComments = 0;
let totalSyncedComments = 0;

const syncComments = async (commentQueue: any[], dispatch: Redux.Dispatch<Redux.Action>) => {
const syncComments = async (commentQueue: any[], dispatch: Redux.Dispatch<Redux.Action>, commentType: String) => {
// We need to throttle the amount of parallel sync requests that we make
// because large forums could be syncing thousands of comments
const maxParallelRequests = 100;
const parallelRequests: Promise <void> [] = [];

for (let comment of commentQueue) {
// Make the sync request and add its promise to the queue,
// and remove it from queue when complete
Expand All @@ -76,6 +75,8 @@ const syncComments = async (commentQueue: any[], dispatch: Redux.Dispatch<Redux.
).then(() => {
parallelRequests.splice(parallelRequests.indexOf(requestPromise), 1);
syncedComments += 1;
}).catch (() => {
console.error('could not sync comment: ', comment);
});
parallelRequests.push(requestPromise);

Expand All @@ -85,12 +86,14 @@ const syncComments = async (commentQueue: any[], dispatch: Redux.Dispatch<Redux.
await Promise.race(parallelRequests);
}
}
// Wait for all of the requests to finish
Promise.all(parallelRequests).then(() => {
dispatch(setValueAction('isManualSyncRunning', false));
// We sync parent comments first then child comments immediately after, so we only update the state of the sync after child comments
if (commentType === 'childComments') {
dispatch(setValueAction('isManualSyncRunning', false));
}
dispatch(updateSyncStatusAction({
is_manual: true,
progress_message: `Complete (${syncedComments} of ${totalSyncedComments})`,
progress_message: `Completed (${syncedComments} of ${totalSyncedComments})`,
}));
});
}
Expand Down Expand Up @@ -151,7 +154,8 @@ const mapDispatchToProps = (dispatch: Redux.Dispatch<Redux.Action>) => {
const endDate: Moment = getDateFromInput(rangeEndInput);

// Create a queue of comments within the provided date-range from the Disqus API
let commentQueue: any[] = [];
const parentCommentList: any[] = [];
const childCommentList: any[] = [];
const getDisqusComments = async (cursor: string = '') => {
return new Promise((resolve, reject) => {
DisqusApi.instance.listPostsForForum(cursor, startDate, endDate, 100, async (xhr: Event) => {
Expand All @@ -171,33 +175,43 @@ const mapDispatchToProps = (dispatch: Redux.Dispatch<Redux.Action>) => {
last_message: null,
}));
}

const pendingComments = disqusData.response;
totalSyncedComments += pendingComments.length;

pendingComments.forEach((comment: any) => {
commentQueue.push(comment);
if (comment.parent) {
childCommentList.push(comment);
} else {
parentCommentList.push(comment);
}
});

const nextCursor = disqusData.cursor;
if (nextCursor && nextCursor.hasNext) {
await getDisqusComments(nextCursor.next);
}
resolve(commentQueue);
resolve([parentCommentList, childCommentList]);
});
});
};

dispatch(setValueAction('isManualSyncRunning', true));
getDisqusComments().then((commentQueue: any[]) => {
syncComments(commentQueue, dispatch);
}).catch((err: any) => {
dispatch(setMessageAction({
onDismiss: handleClearMessage,
text: (err && err.response) || 'Error connecting to the Disqus API',
type: 'error',
}));
});
getDisqusComments()
.then((commentQueue: any[]) => {
syncComments(commentQueue[0], dispatch, 'parentComments');
return commentQueue;
})
.then((commentQueue: any[]) => {
syncComments(commentQueue[1], dispatch, 'childComments');
})
.catch((err: any) => {
dispatch(setMessageAction({
onDismiss: handleClearMessage,
text: (err && err.response) || 'Error connecting to the Disqus API',
type: 'error',
}));
});
},
onSubmitSiteForm: (event: React.SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
Expand Down

0 comments on commit 18d3cf1

Please sign in to comment.