Avoid race conditions when queueing a story for download
This commit is contained in:
parent
0a81376ca0
commit
584b39baa8
2 changed files with 42 additions and 4 deletions
|
@ -52,6 +52,7 @@ import { viewedReceiptsJobQueue } from '../../jobs/viewedReceiptsJobQueue';
|
||||||
export type StoryDataType = {
|
export type StoryDataType = {
|
||||||
attachment?: AttachmentType;
|
attachment?: AttachmentType;
|
||||||
messageId: string;
|
messageId: string;
|
||||||
|
startedDownload?: boolean;
|
||||||
} & Pick<
|
} & Pick<
|
||||||
MessageAttributesType,
|
MessageAttributesType,
|
||||||
| 'canReplyToStory'
|
| 'canReplyToStory'
|
||||||
|
@ -92,6 +93,7 @@ export type StoriesStateType = {
|
||||||
const DOE_STORY = 'stories/DOE';
|
const DOE_STORY = 'stories/DOE';
|
||||||
const LOAD_STORY_REPLIES = 'stories/LOAD_STORY_REPLIES';
|
const LOAD_STORY_REPLIES = 'stories/LOAD_STORY_REPLIES';
|
||||||
const MARK_STORY_READ = 'stories/MARK_STORY_READ';
|
const MARK_STORY_READ = 'stories/MARK_STORY_READ';
|
||||||
|
const QUEUE_STORY_DOWNLOAD = 'stories/QUEUE_STORY_DOWNLOAD';
|
||||||
const REPLY_TO_STORY = 'stories/REPLY_TO_STORY';
|
const REPLY_TO_STORY = 'stories/REPLY_TO_STORY';
|
||||||
export const RESOLVE_ATTACHMENT_URL = 'stories/RESOLVE_ATTACHMENT_URL';
|
export const RESOLVE_ATTACHMENT_URL = 'stories/RESOLVE_ATTACHMENT_URL';
|
||||||
const STORY_CHANGED = 'stories/STORY_CHANGED';
|
const STORY_CHANGED = 'stories/STORY_CHANGED';
|
||||||
|
@ -116,6 +118,11 @@ type MarkStoryReadActionType = {
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type QueueStoryDownloadActionType = {
|
||||||
|
type: typeof QUEUE_STORY_DOWNLOAD;
|
||||||
|
payload: string;
|
||||||
|
};
|
||||||
|
|
||||||
type ReplyToStoryActionType = {
|
type ReplyToStoryActionType = {
|
||||||
type: typeof REPLY_TO_STORY;
|
type: typeof REPLY_TO_STORY;
|
||||||
payload: MessageAttributesType;
|
payload: MessageAttributesType;
|
||||||
|
@ -155,6 +162,7 @@ export type StoriesActionType =
|
||||||
| MessageChangedActionType
|
| MessageChangedActionType
|
||||||
| MessageDeletedActionType
|
| MessageDeletedActionType
|
||||||
| MessagesAddedActionType
|
| MessagesAddedActionType
|
||||||
|
| QueueStoryDownloadActionType
|
||||||
| ReplyToStoryActionType
|
| ReplyToStoryActionType
|
||||||
| ResolveAttachmentUrlActionType
|
| ResolveAttachmentUrlActionType
|
||||||
| StoryChangedActionType
|
| StoryChangedActionType
|
||||||
|
@ -431,7 +439,7 @@ function queueStoryDownload(
|
||||||
void,
|
void,
|
||||||
RootStateType,
|
RootStateType,
|
||||||
unknown,
|
unknown,
|
||||||
NoopActionType | ResolveAttachmentUrlActionType
|
NoopActionType | QueueStoryDownloadActionType | ResolveAttachmentUrlActionType
|
||||||
> {
|
> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const { stories } = getState().stories;
|
const { stories } = getState().stories;
|
||||||
|
@ -477,7 +485,11 @@ function queueStoryDownload(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDownloading(attachment)) {
|
// isDownloading checks for the downloadJobId which is set by
|
||||||
|
// queueAttachmentDownloads but we optimistically set story.startedDownload
|
||||||
|
// in redux to prevent race conditions from queuing up multiple attachment
|
||||||
|
// downloads before the attachment save takes place.
|
||||||
|
if (isDownloading(attachment) || story.startedDownload) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +500,13 @@ function queueStoryDownload(
|
||||||
// completed attachment download.
|
// completed attachment download.
|
||||||
message.set({ storyReplyContext: undefined });
|
message.set({ storyReplyContext: undefined });
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: QUEUE_STORY_DOWNLOAD,
|
||||||
|
payload: storyId,
|
||||||
|
});
|
||||||
|
|
||||||
await queueAttachmentDownloads(message.attributes);
|
await queueAttachmentDownloads(message.attributes);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -1205,5 +1223,25 @@ export function reducer(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action.type === QUEUE_STORY_DOWNLOAD) {
|
||||||
|
const storyIndex = state.stories.findIndex(
|
||||||
|
story => story.messageId === action.payload
|
||||||
|
);
|
||||||
|
|
||||||
|
if (storyIndex < 0) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingStory = state.stories[storyIndex];
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
stories: replaceIndex(state.stories, storyIndex, {
|
||||||
|
...existingStory,
|
||||||
|
startedDownload: true,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,8 +202,8 @@ describe('both/state/ducks/stories', () => {
|
||||||
await queueStoryDownload(storyId)(dispatch, getState, null);
|
await queueStoryDownload(storyId)(dispatch, getState, null);
|
||||||
|
|
||||||
sinon.assert.calledWith(dispatch, {
|
sinon.assert.calledWith(dispatch, {
|
||||||
type: 'NOOP',
|
type: 'stories/QUEUE_STORY_DOWNLOAD',
|
||||||
payload: null,
|
payload: storyId,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue