Skip to content

Commit 45e1bd8

Browse files
Merge #543
543: Simplify task fetching to avoid timeout in strapi v3 r=bidoubiwa a=bidoubiwa Tests in cypress were failing because of a weird tasks listener. I simplified it by removing the complex system to listen to tasks and replacing it with a setInterval running until no tasks are left enqueued or processing. Co-authored-by: Charlotte Vermandel <[email protected]> Co-authored-by: cvermand <[email protected]>
2 parents eae787e + c19a200 commit 45e1bd8

File tree

4 files changed

+31
-220
lines changed

4 files changed

+31
-220
lines changed

admin/src/components/Collections.js

Lines changed: 28 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -21,92 +21,18 @@ import { headers } from '../utils/collection-header'
2121
*/
2222
const Collections = ({ updateCredentials }) => {
2323
const [collectionsList, setCollectionsList] = useState([]) // All Collections
24-
const [upToDateCollections, setUpToDateCollection] = useState(false) // Boolean that informs if collections have been updated.
2524
const [needReload, setNeedReload] = useState(false) // Boolean to inform that reload is requested.
26-
const [collectionInWaitMode, setCollectionInWaitMode] = useState([]) // Collections that are waiting for their indexation to complete.
27-
const [collectionTaskUids, setCollectionTaskUids] = useState({}) // List of collection's enqueued task uids.
25+
const [realTimeReports, setRealTimeReports] = useState(false) // List of collection's enqueued task uids.
26+
const [refetchIndex, setRefetchIndex] = useState(true)
2827

29-
// Trigger a task uids fetcher to find enqueued task of the indexed collections.
30-
useEffect(() => {
31-
findTaskUids()
32-
}, [])
28+
const refetchCollection = () =>
29+
setRefetchIndex(prevRefetchIndex => !prevRefetchIndex)
3330

3431
// Adds a listener that informs if collections have been updated.
3532
useEffect(() => {
36-
setUpToDateCollection(false)
33+
refetchCollection()
3734
}, [updateCredentials])
3835

39-
// Adds a listener that updates collections informations on updates
40-
useEffect(() => {
41-
if (!upToDateCollections) fetchCollections()
42-
}, [upToDateCollections, updateCredentials])
43-
44-
// Trigger a watch if a collection has enqueued task uid's.
45-
useEffect(() => {
46-
for (const collection in collectionTaskUids) {
47-
if (collectionTaskUids[collection].length > 0) {
48-
watchTasks({ collection })
49-
}
50-
}
51-
}, [collectionTaskUids])
52-
53-
/**
54-
* Find all enqueued task uid's of the indexed collections.
55-
* It is triggered on load.
56-
*/
57-
const findTaskUids = async () => {
58-
const response = await request(`/${pluginId}/collection/tasks`, {
59-
method: 'GET',
60-
})
61-
62-
if (response.error) errorNotifications(response)
63-
setCollectionTaskUids(response.taskUids)
64-
}
65-
66-
/**
67-
* Watches a collection (if not already)
68-
* For a maximum of 5 enqueued tasks in Meilisearch.
69-
*
70-
* @param {string} collection - Collection name.
71-
*/
72-
const watchTasks = async ({ collection }) => {
73-
// If collection has pending tasks
74-
const taskUids = collectionTaskUids[collection]
75-
76-
if (!collectionInWaitMode.includes(collection) && taskUids?.length > 0) {
77-
addIndexedStatus
78-
setCollectionInWaitMode(prev => [...prev, collection])
79-
80-
const taskUidsIdsChunk = taskUids.splice(0, 1)
81-
const response = await request(
82-
`/${pluginId}/collection/${collection}/tasks/batch`,
83-
{
84-
method: 'POST',
85-
body: { taskUids: taskUidsIdsChunk },
86-
}
87-
)
88-
89-
if (response.error) errorNotifications(response)
90-
91-
const { tasksStatus } = response
92-
93-
tasksStatus.map(task => {
94-
if (task.status === 'failed') {
95-
task.error.message = `Some documents could not be added: \n${task.error.message}`
96-
errorNotifications(task.error)
97-
}
98-
})
99-
100-
setCollectionInWaitMode(prev => prev.filter(col => col !== collection))
101-
setCollectionTaskUids(prev => ({
102-
...prev,
103-
[collection]: taskUids,
104-
}))
105-
106-
setUpToDateCollection(false) // Ask for collections to be updated.
107-
}
108-
}
109-
11036
/**
11137
* Add a collection to Meilisearch
11238
*
@@ -122,14 +48,7 @@ const Collections = ({ updateCredentials }) => {
12248

12349
createResponseNotification(response, `${collection} is created!`)
12450

125-
if (!response.error) {
126-
setCollectionTaskUids(prev => ({
127-
...prev,
128-
[collection]: response.taskUids,
129-
}))
130-
}
131-
132-
setUpToDateCollection(false) // Ask for collections to be updated.
51+
refetchCollection()
13352
}
13453

13554
/**
@@ -147,14 +66,7 @@ const Collections = ({ updateCredentials }) => {
14766

14867
createResponseNotification(response, `${collection} update started!`)
14968

150-
if (!response.error) {
151-
setCollectionTaskUids(prev => ({
152-
...prev,
153-
[collection]: response.taskUids,
154-
}))
155-
}
156-
157-
setUpToDateCollection(false) // Ask for collections to be updated.
69+
refetchCollection()
15870
}
15971

16072
/**
@@ -172,7 +84,7 @@ const Collections = ({ updateCredentials }) => {
17284
`${collection} collection is removed from Meilisearch!`
17385
)
17486

175-
setUpToDateCollection(false) // Ask for collections to be updated.
87+
refetchCollection()
17688
}
17789

17890
/**
@@ -200,12 +112,9 @@ const Collections = ({ updateCredentials }) => {
200112

201113
if (error) errorNotifications(res)
202114
else {
203-
// Start watching collections that have pending tasks
204-
collections.map(col => {
205-
if (col.isIndexing) {
206-
watchTasks({ collection: col.collection })
207-
}
208-
})
115+
const isIndexing = collections.find(col => col.isIndexing === true)
116+
117+
setRealTimeReports(isIndexing)
209118

210119
// Transform collections information to verbose string.
211120
const renderedCols = collections.map(col => transformCollections(col))
@@ -217,10 +126,26 @@ const Collections = ({ updateCredentials }) => {
217126

218127
setNeedReload(reloading) // A reload is required for a collection to be listened or de-listened
219128
setCollectionsList(renderedCols) // Store all `Strapi collections
220-
setUpToDateCollection(true) // Collection information is up to date
221129
}
222130
}
223131

132+
// Start refreshing the collections when a collection is being indexed
133+
useEffect(() => {
134+
let interval
135+
if (realTimeReports) {
136+
interval = setInterval(() => {
137+
refetchCollection()
138+
}, 1000)
139+
} else {
140+
clearInterval(interval)
141+
}
142+
return () => clearInterval(interval)
143+
}, [realTimeReports])
144+
145+
useEffect(() => {
146+
fetchCollections()
147+
}, [refetchIndex])
148+
224149
return (
225150
<div className="col-md-12">
226151
<Wrapper>

config/routes.json

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,6 @@
3232
"policies": ["isAdmin"]
3333
}
3434
},
35-
{
36-
"method": "POST",
37-
"path": "/collection/:collection/tasks/batch",
38-
"handler": "meilisearch.waitForTasks",
39-
"config": {
40-
"policies": ["isAdmin"]
41-
}
42-
},
43-
{
44-
"method": "GET",
45-
"path": "/collection/tasks",
46-
"handler": "meilisearch.getTaskUids",
47-
"config": {
48-
"policies": ["isAdmin"]
49-
}
50-
},
5135
{
5236
"method": "POST",
5337
"path": "/collections/:collection",

connectors/meilisearch/index.js

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -66,49 +66,6 @@ module.exports = async ({ storeConnector, collectionConnector }) => {
6666
await client.index(indexUid).deleteDocuments(documentsIds)
6767
},
6868

69-
/**
70-
* Wait for an task to be processed in Meilisearch.
71-
*
72-
* @param {string} collection - Collection name.
73-
* @param {number} taskUid - Task identifier.
74-
*
75-
* @returns {{Record<string, string>}} - Task body returned by Meilisearch API.
76-
*/
77-
waitForTask: async function ({ collection, taskUid }) {
78-
try {
79-
const client = MeiliSearch({ apiKey, host })
80-
const indexUid = collectionConnector.getIndexName(collection)
81-
const task = await client
82-
.index(indexUid)
83-
.waitForTask(taskUid, { intervalMs: 5000 })
84-
85-
return task
86-
} catch (e) {
87-
console.error(e)
88-
return 0
89-
}
90-
},
91-
92-
/**
93-
* Wait for a batch of tasks uids to be processed.
94-
*
95-
* @param {string} collection - Collection name.
96-
* @param {number[]} taskUids - Array of tasks identifiers.
97-
*
98-
* @returns { Record<string, string>[] } - List of all tasks returned by Meilisearch API.
99-
*/
100-
waitForTasks: async function ({ collection, taskUids }) {
101-
const tasks = []
102-
for (const taskUid of taskUids) {
103-
const status = await this.waitForTask({
104-
collection,
105-
taskUid,
106-
})
107-
tasks.push(status)
108-
}
109-
return tasks
110-
},
111-
11269
/**
11370
* Get indexes with a safe guard in case of error.
11471
*
@@ -117,6 +74,7 @@ module.exports = async ({ storeConnector, collectionConnector }) => {
11774
getIndexes: async function () {
11875
try {
11976
const client = MeiliSearch({ apiKey, host })
77+
12078
const { results } = await client.getIndexes()
12179
return results
12280
} catch (e) {
@@ -141,32 +99,6 @@ module.exports = async ({ storeConnector, collectionConnector }) => {
14199
}
142100
},
143101

144-
/**
145-
* Get enqueued tasks ids of indexed collections.
146-
*
147-
* @returns { { string: number[] } } - Collections with their respective task uids
148-
*/
149-
getTaskUids: async function () {
150-
const indexes = await this.getIndexes()
151-
const indexUids = indexes.map(index => index.uid)
152-
const collections = collectionConnector.allEligbleCollections()
153-
const client = MeiliSearch({ apiKey, host })
154-
155-
const collectionTaskUids = {}
156-
for (const collection of collections) {
157-
const indexUid = collectionConnector.getIndexName(collection)
158-
if (indexUids.includes(indexUid)) {
159-
const { results: tasks } = await client.index(indexUid).getTasks()
160-
161-
const enqueueded = tasks
162-
.filter(task => task.status === 'enqueued')
163-
.map(task => task.uid)
164-
collectionTaskUids[collection] = enqueueded
165-
}
166-
}
167-
return collectionTaskUids
168-
},
169-
170102
/**
171103
* Information about collections in Meilisearch.
172104
*

controllers/meilisearch.js

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -130,37 +130,9 @@ async function addCollection(ctx) {
130130
const connector = await createConnector()
131131
const { collection } = ctx.params
132132
const taskUids = await connector.addCollectionInMeiliSearch(collection)
133-
return { message: 'Index created', taskUids }
134-
}
135-
136-
/**
137-
* Wait for one collection to be completely indexed in Meilisearch.
138-
*
139-
* @param {object} ctx - Http request object.
140-
*
141-
* @returns { numberOfDocumentsIndexed: number }
142-
*/
143-
async function waitForTasks(ctx) {
144-
const connector = await createConnector()
145-
const { collection } = ctx.params
146-
const { taskUids } = ctx.request.body
147-
const tasksStatus = await connector.waitForTasks({
148-
taskUids,
149-
collection,
150-
})
151-
return { tasksStatus }
152-
}
133+
console.log({ taskUids })
153134

154-
/**
155-
* Wait for one collection to be completely indexed in Meilisearch.
156-
*
157-
* @returns { taskUids: number[] }
158-
*/
159-
async function getTaskUids() {
160-
const connector = await createConnector()
161-
const taskUids = await connector.getTaskUids()
162-
163-
return { taskUids }
135+
return { message: 'Index created', taskUids }
164136
}
165137

166138
/**
@@ -180,7 +152,5 @@ module.exports = {
180152
addCredentials: async ctx => ctxWrapper(ctx, addCredentials),
181153
removeCollection: async ctx => ctxWrapper(ctx, removeCollection),
182154
updateCollections: async ctx => ctxWrapper(ctx, updateCollections),
183-
waitForTasks: async ctx => ctxWrapper(ctx, waitForTasks),
184-
getTaskUids: async ctx => ctxWrapper(ctx, getTaskUids),
185155
reload: async ctx => ctxWrapper(ctx, reload),
186156
}

0 commit comments

Comments
 (0)