Skip to content

Commit

Permalink
feat: Allow to enforce Stack link on request chain
Browse files Browse the repository at this point in the history
In previous commits we implemented supports for offline mode through
CozyPouchLink and FlagshipLink

Since this feature, the StackLink is able to check for internet
reachability by using the `isOnline()` method. When no internet is
detected, then the request is forwarded to the next link (i.e. the
CozyPouchLink)

In some scenario we may want to prevent that behavior. This is the case
when we are working on a feature that cannot work without internet
access, or when the query's result is expected to contain data that is
injected by the cozy-stack (and so that is not available in the local
Pouch database)

To make this possible we introduce the `forceStack` parameter that can
be set in the query options

When set to `true` then the StackLink will not attempt to forward the
request when offline, instead it will still attempt to do the request
and throw

We chose to attempt the request instead of directly throwing an error
in order to prevent hypothetical scenario where `isOnline()` method
returns false even if internet is reachable
  • Loading branch information
Ldoppea committed Dec 17, 2024
1 parent 3b397e6 commit 4aba700
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 33 deletions.
8 changes: 4 additions & 4 deletions docs/link-authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ In the chain example pictured above, the Dedup link would avoid re-fetching the
There are two ways of creating a new link. First, you can instantiate a `CozyLink` and pass a request handling function to its constructor:

```js
const logLink = new CozyLink((operation, result, forward) => {
const logLink = new CozyLink((operation, options, result, forward) => {
console.log(JSON.stringify(operation))
return forward(operation, result)
return forward(operation, options, result)
})
```

Or you can subclass `CozyLink`:

```js
class LogLink extends CozyLink {
request(operation, result, forward) {
request(operation, options, result, forward) {
console.log(JSON.stringify(operation))
return forward(operation, result)
return forward(operation, options, result)
}
}
```
Expand Down
12 changes: 6 additions & 6 deletions packages/cozy-client/src/CozyClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ client.query(Q('io.cozy.bills'))`)
Promise.resolve(
executeQueryFromState(this.store.getState(), queryDefinition)
)
: () => this.requestQuery(queryDefinition)
: () => this.requestQuery(queryDefinition, options)
const response = await this._promiseCache.exec(requestFn, () =>
stringify(queryDefinition)
)
Expand Down Expand Up @@ -1085,7 +1085,7 @@ client.query(Q('io.cozy.bills'))`)
options.as || this.queryIdGenerator.generateId(mutationDefinition)
this.dispatch(initMutation(mutationId, mutationDefinition))
try {
const response = await this.requestMutation(mutationDefinition)
const response = await this.requestMutation(mutationDefinition, options)
this.dispatch(
receiveMutationResult(
mutationId,
Expand All @@ -1111,8 +1111,8 @@ client.query(Q('io.cozy.bills'))`)
* @param {QueryDefinition} definition QueryDefinition to be executed
* @returns {Promise<import("./types").ClientResponse>}
*/
async requestQuery(definition) {
const mainResponse = await this.chain.request(definition)
async requestQuery(definition, options) {
const mainResponse = await this.chain.request(definition, options)

await this.persistVirtualDocuments(definition, mainResponse.data)

Expand Down Expand Up @@ -1262,7 +1262,7 @@ client.query(Q('io.cozy.bills'))`)
}
}

async requestMutation(definition) {
async requestMutation(definition, options) {
if (Array.isArray(definition)) {
const [first, ...rest] = definition
const firstResponse = await this.requestMutation(first)
Expand All @@ -1275,7 +1275,7 @@ client.query(Q('io.cozy.bills'))`)
)
return firstResponse
}
return this.chain.request(definition)
return this.chain.request(definition, options)
}

getIncludesRelationships(queryDefinition) {
Expand Down
10 changes: 5 additions & 5 deletions packages/cozy-client/src/CozyLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class CozyLink {
* @param {any} forward - The next request of the chain
* @returns {Promise<any>}
*/
async request(operation, result, forward) {
async request(operation, options, result, forward) {
throw new Error('request is not implemented')
}

Expand Down Expand Up @@ -67,11 +67,11 @@ export const chain = links =>
[...links, defaultLinkHandler].map(toLink).reduce(concat)

const concat = (firstLink, nextLink) => {
const requestHandler = (operation, result, forward) => {
const nextForward = (op, res) => {
return nextLink.request(op, res, forward)
const requestHandler = (operation, options, result, forward) => {
const nextForward = (op, options, res) => {
return nextLink.request(op, options, res, forward)
}
return firstLink.request(operation, result, nextForward)
return firstLink.request(operation, options, result, nextForward)
}

const persistHandler = (data, forward) => {
Expand Down
16 changes: 8 additions & 8 deletions packages/cozy-client/src/StackLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,19 @@ export default class StackLink extends CozyLink {
this.stackClient = null
}

async request(operation, result, forward) {
if (this.isOnline && !(await this.isOnline())) {
return forward(operation)
async request(operation, options, result, forward) {
if (this.isOnline && !(await this.isOnline()) && !options?.forceStack) {
return forward(operation, options)
}

try {
if (operation.mutationType) {
return await this.executeMutation(operation, result, forward)
return await this.executeMutation(operation, options, result, forward)
}
return await this.executeQuery(operation)
} catch (err) {
if (isReactNativeOfflineError(err)) {
return forward(operation)
if (isReactNativeOfflineError(err) && !options?.forceStack) {
return forward(operation, options)
}
throw err
}
Expand Down Expand Up @@ -138,7 +138,7 @@ export default class StackLink extends CozyLink {
}
}

async executeMutation(mutation, result, forward) {
async executeMutation(mutation, options, result, forward) {
const { mutationType, document: doc, documents: docs, ...props } = mutation
switch (mutationType) {
case MutationTypes.CREATE_DOCUMENT:
Expand Down Expand Up @@ -182,7 +182,7 @@ export default class StackLink extends CozyLink {
.collection(DOCTYPE_FILES)
.upload(props.file, props.dirPath)
default:
return forward(mutation, result)
return forward(mutation, options, result)
}
}
}
4 changes: 2 additions & 2 deletions packages/cozy-client/src/WebFlagshipLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export default class WebFlagshipLink extends CozyLink {
// does nothing, we don't need any client for this kind of link
}

async request(operation, result, forward) {
return this.webviewIntent.call('flagshipLinkRequest', operation)
async request(operation, options, result, forward) {
return this.webviewIntent.call('flagshipLinkRequest', operation, options)
}

async persistCozyData(data, forward) {
Expand Down
16 changes: 8 additions & 8 deletions packages/cozy-pouch-link/src/CozyPouchLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ class PouchLink extends CozyLink {
return !!this.getPouch(impactedDoctype)
}

async request(operation, result = null, forward = doNothing) {
async request(operation, options, result = null, forward = doNothing) {
const doctype = getDoctypeFromOperation(operation)

if (!this.pouches) {
Expand All @@ -420,7 +420,7 @@ class PouchLink extends CozyLink {
)
}

return forward(operation)
return forward(operation, options)
}

if (this.pouches.getSyncStatus(doctype) === 'not_synced') {
Expand All @@ -429,7 +429,7 @@ class PouchLink extends CozyLink {
`Tried to access local ${doctype} but Cozy Pouch is not synced yet. Forwarding the operation to next link`
)
}
return forward(operation)
return forward(operation, options)
}

if (await this.needsToWaitWarmup(doctype)) {
Expand All @@ -438,7 +438,7 @@ class PouchLink extends CozyLink {
`Tried to access local ${doctype} but not warmuped yet. Forwarding the operation to next link`
)
}
return forward(operation)
return forward(operation, options)
}

// Forwards if doctype not supported
Expand All @@ -448,11 +448,11 @@ class PouchLink extends CozyLink {
`The doctype '${doctype}' is not supported. Forwarding the operation to next link`
)
}
return forward(operation)
return forward(operation, options)
}

if (operation.mutationType) {
return this.executeMutation(operation, result, forward)
return this.executeMutation(operation, options, result, forward)
} else {
return this.executeQuery(operation)
}
Expand Down Expand Up @@ -749,7 +749,7 @@ class PouchLink extends CozyLink {
return jsonResult
}

async executeMutation(mutation, result, forward) {
async executeMutation(mutation, options, result, forward) {
const markName = this.performancesApi.mark('executeMutation')
let pouchRes
switch (mutation.mutationType) {
Expand All @@ -769,7 +769,7 @@ class PouchLink extends CozyLink {
pouchRes = await this.addReferencesTo(mutation)
break
default:
return forward(mutation, result)
return forward(mutation, options, result)
}

const jsonResult = jsonapi.fromPouchResult({
Expand Down

0 comments on commit 4aba700

Please sign in to comment.