I’m currently working on an asynchronous function backgroundProcess that processes items produced by a producer function and consumes them with a consumer function. However, I’m encountering an issue with the status management of the process. Specifically, one of my tests fails when checking if the status is Running while the process is being executed.
Here’s a simplified version of the backgroundProcess function:
/**
* Exercise 6, 1.5 points
*
* @param {()=>Promise} produce
* @param {(data:any)=>Promise} consume
* @returns
*/
export function backgroundProcess(produce, consume) {
let available = []
let totalProduced = 0
let status = 0 // 0 = Idle, 1 = Running, 2 = Finished
let intervalId
let isFirstCall = true
let hasStarted = false
const startProcess = async () => {
if (hasStarted) return // Prevent starting if it's already running
status = 1 // Change status to Running
hasStarted = true
intervalId = setInterval(async () => {
try {
const products = await produce()
if (products === null) {
clearInterval(intervalId)
status = 2 // Change status to Finished
return
}
for (const product of products) {
const consumed = await consume(product)
available.push(consumed)
totalProduced++
}
} catch (error) {
// Handle error if needed
console.error('Error in producing or consuming:', error)
}
}, 100)
}
return function getStatus() {
if (isFirstCall && !hasStarted) {
isFirstCall = false
return {
available: [],
totalProduced: 0,
status: 0,
}
}
if (status === 0) {
startProcess() // Start the process if it's idle
}
const result = {
available: [...available],
totalProduced,
status,
}
available = [] // Clear available after each invocation
return result
}
}
And here’s the relevant test that is failing:
test('It should have status=1 if the process is being executed', async () => {
const array = [[1, 2, 3], [4, 5, 6], [7, 8, 9], null]
const producer = createProducer(array)
const fn = backgroundProcess(producer, defaultConsumer())
await sleep(MAX_MS)
const result = fn()
expect(result.status).toBe(STATUSES.Running)
})
My package.json includes:
src/pec3/pec3.test.js
backgroundProcess
√ It should return an async function (2 ms)
√ It should return the right structure after invoking returned function (1 ms)
√ It should finish in a finite amount of time (373 ms)
√ It should call producer the right amount of times (691 ms)
√ It should call consumer the right amount of times (463 ms)
√ It should clear the production queue after each invocation of the resulting function (782 ms)
√ It should count the number of products produced in background (931 ms)
× It should have status=0 if the process has not been started yet (2 ms)
√ It should have status=1 if the process is being executed (111 ms)
√ It should have status=2 if the process has finished (248 ms)
● backgroundProcess › It should have status=0 if the process has not been started yet
expect(received).toBe(expected) // Object.is equality
Expected: 0
Received: 1
211 | test('It should have status=0 if the process has not been started yet', async () => {
212 | const fn = backgroundProcess(defaultProducer(), defaultConsumer())
> 213 | expect(fn().status).toBe(STATUSES.Idle)
| ^
214 |
215 | await processCompleted(fn)
216 | })
at Object.<anonymous> (src/pec3/pec3.test.js:213:25)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 9 passed, 10 total
Snapshots: 0 total
Time: 5.339 s, estimated 6 s
Ran all test suites.
I have verified that the producer and consumer functions are set up correctly, but it seems that the status remains Idle when it should be Running.
My package.json includes:
{
"name": "pec-0-sol",
"version": "0.1.0",
"private": true,
"type": "module",
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/user-event": "^13.5.0",
"pec-0-sol": "file:",
"react-scripts": "5.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
I suspect that there may be a timing issue related to how the setInterval is functioning or how the status is being updated. Can anyone help me identify the root cause of this issue?
Feel free to adjust any details to fit your style better. Once you’re satisfied with the question, you can post it on Stack Overflow to get help from the community!