generated from graasp/graasp-repo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add etherpad fetch queue (#424)
- Loading branch information
Alexandre Chau
authored
Sep 21, 2023
1 parent
e34cc2d
commit 2b339f8
Showing
3 changed files
with
83 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { EtherpadItemType, Item, UUID } from '@graasp/sdk'; | ||
|
||
import axios from 'axios'; | ||
|
||
import { QueryClientConfig } from '../types'; | ||
import { verifyAuthentication } from './axios'; | ||
import { buildGetEtherpadRoute, buildPostEtherpadRoute } from './routes'; | ||
|
||
/** | ||
* This is a queue singleton class that manages querying etherpads | ||
* It ensures that they are always retrieved sequentially (i.e. always after the previous is resolved) | ||
* This is required because the etherpad sessions are given in a single cookie which must be constructed cumulatively | ||
* To ensure that there is no race condition between requests in a given browser tab, this queue sends them one after the other | ||
*/ | ||
class EtherpadQueue { | ||
/** Ensure singleton with a single instance */ | ||
static readonly instance = new EtherpadQueue(); | ||
|
||
/** A reference to the last promise added to the queue */ | ||
private lastPromise = Promise.resolve(); | ||
|
||
/** Ensure singleton with private constructor */ | ||
// eslint-disable-next-line no-useless-constructor, no-empty-function | ||
private constructor() {} | ||
|
||
public getEtherpad( | ||
{ itemId, mode }: { itemId: UUID; mode: 'read' | 'write' }, | ||
{ API_HOST }: QueryClientConfig, | ||
) { | ||
const doFetch = () => | ||
axios | ||
.get(`${API_HOST}/${buildGetEtherpadRoute(itemId)}`, { | ||
params: { mode }, | ||
}) | ||
.then(({ data }) => data); | ||
// The queue is implicitly managed by the nested promises call stack | ||
// We simply schedule this request after the last one that was set | ||
// We CANNOT use this.lastPromise.finally(doFetch)! The finally semantics will return the previous return value, even if failing! | ||
// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally#description | ||
// instead we use .then(onResolve, onRejected) with both arguments set to doFetch | ||
const nextPromise = this.lastPromise.then(doFetch, doFetch); | ||
this.lastPromise = nextPromise; | ||
// Retuning the previous reference allows multiple then / catch calls | ||
return nextPromise; | ||
} | ||
} | ||
|
||
export const postEtherpad = async ( | ||
{ | ||
name, | ||
parentId, | ||
}: Pick<Item, 'name'> & { | ||
parentId?: UUID; | ||
}, | ||
{ API_HOST }: QueryClientConfig, | ||
): Promise<EtherpadItemType> => | ||
verifyAuthentication(() => | ||
axios | ||
.post(`${API_HOST}/${buildPostEtherpadRoute(parentId)}`, { | ||
name: name.trim(), | ||
}) | ||
.then(({ data }) => data), | ||
); | ||
|
||
export const getEtherpad = ( | ||
args: { itemId: UUID; mode: 'read' | 'write' }, | ||
queryConfig: QueryClientConfig, | ||
) => EtherpadQueue.instance.getEtherpad(args, queryConfig); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,21 @@ | ||
export * from './action'; | ||
export * from './apps'; | ||
export * from './member'; | ||
export * from './item'; | ||
export * from './membership'; | ||
export * from './authentication'; | ||
export * from './itemTag'; | ||
export * from './itemLogin'; | ||
export * from './itemFlag'; | ||
export * from './chat'; | ||
export * from './mentions'; | ||
export * from './category'; | ||
export * from './search'; | ||
export * from './chat'; | ||
export * from './etherpad'; | ||
export * from './invitation'; | ||
export * from './item'; | ||
export * from './itemExport'; | ||
export * from './itemFavorite'; | ||
export * from './itemFlag'; | ||
export * from './itemLike'; | ||
export * from './itemLogin'; | ||
export * from './itemPublish'; | ||
export * from './itemTag'; | ||
export * from './itemValidation'; | ||
export * from './action'; | ||
export * from './invitation'; | ||
export * from './member'; | ||
export * from './membership'; | ||
export * from './mentions'; | ||
export * from './search'; | ||
export * from './subscription'; | ||
export * from './itemPublish'; | ||
export * from './itemFavorite'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters