Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3353233
D6334.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D6334.diff
View Options
diff --git a/keyserver/src/cron/cron.js b/keyserver/src/cron/cron.js
--- a/keyserver/src/cron/cron.js
+++ b/keyserver/src/cron/cron.js
@@ -21,6 +21,7 @@
import { deleteExpiredUpdates } from '../deleters/update-deleters';
import { deleteUnassignedUploads } from '../deleters/upload-deleters';
import { backupDB } from './backups';
+import { createDailyUpdatesThread } from './daily-updates';
import { updateAndReloadGeoipDB } from './update-geoip-db';
if (cluster.isMaster) {
@@ -61,7 +62,7 @@
},
);
schedule.scheduleJob(
- '0 3 ? * 0', // every Sunday at 3:00 AM Pacific Time
+ '0 3 ? * 0', // every Sunday at 3:00 AM GMT
async () => {
try {
await updateAndReloadGeoipDB();
@@ -73,4 +74,20 @@
}
},
);
+ schedule.scheduleJob(
+ '0 0 * * *', // every day at midnight GMT
+ async () => {
+ try {
+ if (process.env.RUN_COMM_TEAM_DEV_SCRIPTS) {
+ // This is a job that the Comm internal team uses
+ await createDailyUpdatesThread();
+ }
+ } catch (e) {
+ console.warn(
+ 'encountered error while trying to create daily updates thread',
+ e,
+ );
+ }
+ },
+ );
}
diff --git a/keyserver/src/cron/daily-updates.js b/keyserver/src/cron/daily-updates.js
new file mode 100644
--- /dev/null
+++ b/keyserver/src/cron/daily-updates.js
@@ -0,0 +1,101 @@
+// @flow
+
+import invariant from 'invariant';
+
+import ashoat from 'lib/facts/ashoat';
+import { messageTypes } from 'lib/types/message-types';
+import { threadTypes } from 'lib/types/thread-types';
+import {
+ getDate,
+ dateString,
+ prettyDateWithoutYear,
+ prettyDateWithoutDay,
+} from 'lib/utils/date-utils';
+
+import createMessages from '../creators/message-creator';
+import { createThread } from '../creators/thread-creator';
+import { fetchEntryInfosForThreadThisWeek } from '../fetchers/entry-fetchers';
+import { createScriptViewer } from '../session/scripts';
+
+const devUpdateThread = '1358777';
+const weeklyDevSyncScheduleThread = '4138372';
+
+const dailyUpdateMessage = (dateWithoutYear: string, dateWithoutDay: string) =>
+ `### ${dateWithoutDay} update
+
+Share your updates for ${dateWithoutYear} here please!`;
+
+const dateIsWeekend = (date: Date) =>
+ date.getDay() === 0 || date.getDay() === 6;
+
+// This function will do something four days a week. It skips Saturday and
+// Sunday. The hard part is the third skipped day, which is the day of the
+// weekly dev sync. By default this is Monday, but if the dev sync is on a
+// different day, then an admin will put a calendar entry in the
+// weeklyDevSyncScheduleThread indicating which day to skip.
+async function createDailyUpdatesThread() {
+ if (!process.env.RUN_COMM_TEAM_DEV_SCRIPTS) {
+ // This is a job that the Comm internal team uses
+ return;
+ }
+
+ const viewer = createScriptViewer(ashoat.id);
+ const now = new Date();
+ if (dateIsWeekend(now)) {
+ // nothing happens on Saturday or Sunday
+ return;
+ }
+
+ // Figure out which day the dev sync is on
+ let devSyncDay = 1; // default to Monday
+ const entryInfosInDevSyncScheduleThreadThisWeek = await fetchEntryInfosForThreadThisWeek(
+ viewer,
+ weeklyDevSyncScheduleThread,
+ );
+ for (const entryInfo of entryInfosInDevSyncScheduleThreadThisWeek) {
+ const entryInfoDate = getDate(
+ entryInfo.year,
+ entryInfo.month,
+ entryInfo.day,
+ );
+ if (dateIsWeekend(entryInfoDate)) {
+ // Ignore calendar entries on weekend
+ continue;
+ }
+ devSyncDay = entryInfoDate.getDay();
+ // Use the newest entryInfo. fetchEntryInfos sorts by creation time
+ break;
+ }
+
+ if (devSyncDay === now.getDay()) {
+ // Skip the dev sync day
+ return;
+ }
+
+ const dayString = dateString(now);
+ const dateWithoutYear = prettyDateWithoutYear(dayString);
+ const dateWithoutDay = prettyDateWithoutDay(dayString);
+
+ const [{ id: messageID }] = await createMessages(viewer, [
+ {
+ type: messageTypes.TEXT,
+ threadID: devUpdateThread,
+ creatorID: ashoat.id,
+ time: Date.now(),
+ text: dailyUpdateMessage(dateWithoutYear, dateWithoutDay),
+ },
+ ]);
+ invariant(
+ messageID,
+ 'message returned from createMessages always has ID set',
+ );
+
+ await createThread(viewer, {
+ type: threadTypes.SIDEBAR,
+ parentThreadID: devUpdateThread,
+ name: `${dateWithoutDay} update`,
+ sourceMessageID: messageID,
+ });
+}
+
+export { createDailyUpdatesThread };
diff --git a/keyserver/src/fetchers/entry-fetchers.js b/keyserver/src/fetchers/entry-fetchers.js
--- a/keyserver/src/fetchers/entry-fetchers.js
+++ b/keyserver/src/fetchers/entry-fetchers.js
@@ -21,6 +21,7 @@
threadPermissions,
type ThreadPermission,
} from 'lib/types/thread-types';
+import { dateString } from 'lib/utils/date-utils';
import { ServerError } from 'lib/utils/errors';
import {
@@ -317,6 +318,30 @@
return rawEntryInfoFromRow(result[0]);
}
+function getSunday(weeksFromLastSunday: number) {
+ const date = new Date();
+ const today = date.getDate();
+ const currentDay = date.getDay();
+ const newDate = date.setDate(today - currentDay + 7 * weeksFromLastSunday);
+ return new Date(newDate);
+}
+
+async function fetchEntryInfosForThreadThisWeek(
+ viewer: Viewer,
+ threadID: string,
+): Promise<$ReadOnlyArray<RawEntryInfo>> {
+ const startDate = dateString(getSunday(0));
+ const endDate = dateString(getSunday(1));
+ const filters = [
+ { type: 'not_deleted' },
+ { type: 'threads', threadIDs: [threadID] },
+ ];
+ const { rawEntryInfos } = await fetchEntryInfos(viewer, [
+ { startDate, endDate, filters },
+ ]);
+ return rawEntryInfos;
+}
+
export {
fetchEntryInfo,
fetchEntryInfosByID,
@@ -325,4 +350,5 @@
fetchEntryRevisionInfo,
fetchEntriesForSession,
fetchEntryInfoForLocalID,
+ fetchEntryInfosForThreadThisWeek,
};
diff --git a/lib/types/filter-types.js b/lib/types/filter-types.js
--- a/lib/types/filter-types.js
+++ b/lib/types/filter-types.js
@@ -14,7 +14,7 @@
+type: 'threads',
+threadIDs: $ReadOnlyArray<string>,
};
-export type CalendarFilter = { type: 'not_deleted' } | CalendarThreadFilter;
+export type CalendarFilter = { +type: 'not_deleted' } | CalendarThreadFilter;
export const defaultCalendarFilters: $ReadOnlyArray<CalendarFilter> = [
{ type: calendarThreadFilterTypes.NOT_DELETED },
diff --git a/lib/utils/date-utils.js b/lib/utils/date-utils.js
--- a/lib/utils/date-utils.js
+++ b/lib/utils/date-utils.js
@@ -73,6 +73,10 @@
return dateFormat(dateFromString(dayString), 'mmmm dS, yyyy');
}
+function prettyDateWithoutYear(dayString: string): string {
+ return dateFormat(dateFromString(dayString), 'dddd, mmmm dS');
+}
+
function dateFromString(dayString: string): Date {
const matches = dayString.match(/^([0-9]+)-([0-1][0-9])-([0-3][0-9])$/);
invariant(matches && matches.length === 4, `invalid dayString ${dayString}`);
@@ -160,6 +164,7 @@
fifteenDaysLater,
prettyDate,
prettyDateWithoutDay,
+ prettyDateWithoutYear,
dateFromString,
shortAbsoluteDate,
longAbsoluteDate,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 24, 8:57 AM (21 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2574755
Default Alt Text
D6334.diff (6 KB)
Attached To
Mode
D6334: [keyserver] Automatically create daily update threads
Attached
Detach File
Event Timeline
Log In to Comment