Bacon.js stream with some okay errors - functional-programming

The result of a PUT operation against a database, is sometimes ok even if it doesn't come back as a HTTP code 200.
In this specific case I want to treat 400 as another okay error, but struggle to come up with an elegant way of doing it.
# stream from a promise any non 200 is fail
putter = Bacon.fromPromise #_exec 'PUT', '/some/resource', {}
errors = putter.errors().mapError(errBody) # now errors are normal values
badErrors = errors.filter(statusIsnt(400)).flatMap (body) ->
return new Bacon.Error body # and now they are errors again
okErrors = errors.filter(statusIs(400)).flatMap (body) -> {}
noError = putter.mapError().filter (v) -> v? # attempt to get rid of errors
Bacon.mergeAll noError, okErrors, badErrors # combine to get result stream
I come from a promises background, and I find the above somewhat clumsy, which leads me to conclude I'm missing something. Compare:
#_exec 'PUT', '/some/resource', {}
.fail (err) ->
if err.body.status == 400 # ok
return {}
else
throw err

You can use withHandler with Bacon.Error for throw and (implicit) Bacon.Next for result. But the code will look very similar to your handling already in promise. Actually promise version has less boilerplate.
Compare your promise version
promise = #_exec('PUT', '/some/resource', {})
recovered = promise.fail (err) ->
# 400 is ok. make it ok already in promise
if err?.body?.status == 400 then {} else throw err.body
result = Bacon.fromPromise recovered
and withHandler Bacon "only" version
promise = #_exec('PUT', '/some/resource', {})
stream = Bacon.fromPromise promise
result = stream.withHandler (event) ->
if (event.hasValue())
#push(event)
else
# error
if event.error?.body?.status == 400 then
#push({})
else
#push(event)

One possible solution for this specific scenario is to amend the result already in the promise, but I can easily envisage cases where you can't do that.
Bacon.fromPromise #_exec('PUT', '/some/resource', {}).fail (err) ->
# 400 is ok. make it ok already in promise
if err?.body?.status == 400 then {} else throw err.body
Surely there must be a better functional approach to this problem?

withHandler is an underlying method that lets you operate on Events of all types. Within it you can call #push, which will send errors to the error stream and values to the value streeam. Perhaps the following:
Bacon.fromPromise(#_exec('PUT', '/some/resource', {}))
.withHandler((event) ->
if event.isError && event.error.body?.status? == 400
#push(new Bacon.Next({}))
else
#push(event)
)

Related

How can I rerun only failed scenarios in the feature in Karate API? [duplicate]

I have a request where i get Processing or Submitted in a response parameter if the request is in process or passed respectively.
I am able to poll and get if the status is "Processing" or"Submitted" but after that I am unable to fail the request if still i am not getting the expected status after polling for 5 times.
How can i fail request after certain retries do not provide me expected response?
The answer is in your question,
I assume you are polling using a js function,
If so you can add a boolean return from that, if you condition not met return false or if condition met return true then assert the value returned from your feature file.
* def pollingFunc =
"""
function(x) {
// your polling logic which retrives status
if (status == x) {
return true;
}
else{
return false;
}
}
"""
In feature
* def statusFound = pollingFunc("Processed" )
* assert (statusFound == true)
If the expected status not obtained after polling the assert will fail the test

Firebase function return value while async action is ongoing [duplicate]

I'm using Firebase Functions with https triggers, and I was wondering how long after sending the response to the client, the functions keeps executing. I want to send a response to the client and then perform another operation (send a mail).
Currently I'm doing this as following:
module.exports.doSomeJob = functions.https.onRequest((req, res) => {
doSomeAsyncJob()
.then(() => {
res.send("Ok");
})
.then(() => {
emailSender.sendEmail();
})
.catch(...);
});
The above code is working for me, but I'm suspecting that the code only works because sending the mail has finished before the res.send has completed, so I was wondering how exactly the termination process is working to make sure the code will not break.
You should expect that the HTTP function terminates the moment after you send the response. Any other behavior is some combination of luck or a race condition. Don't write code that depends on luck.
If you need to send a response to the client before the work is fully complete, you will need to kick off a second function to continue where the HTTP function left off. It's common to use a pub/sub function to do with. Have the HTTP function send a pub/sub message to another function, then terminate the HTTP function (by sending a response) only after the message is sent.
If the expected response is not pegged to the outcome of the execution, then you can use
module.exports.doSomeJob = functions.https.onRequest((req, res) => {
res.write('SUCCESS')
return doSomeAsyncJob()
.then(() => {
emailSender.sendEmail();
})
.then(() => {
res.end();
})
.catch(...);
});
This sends back a response a soon as a request is received, but keeps the function running until res.end() is called
Your client can end the connection as soon as a response is received back, but the cloud function will keep running in the background
Not sure if this helps, but it might be a workaround where the client needs a response within a very limited time, considering that executing pub/sub requires some extra processing on its own and takes time to execute
TL;DR
While https functions will terminate shortly after res.send(), it is not guaranteed that 0 lines of code after res.send() will be executed.
I think a fuller answer has 2 components:
as Doug pointed out, do not put any additional code you expect to be executed after res.send()
cloud functions will terminate shortly after res.send(), but don't expect that exactly 0 lines of code will be executed
I ran into a situation where for a db maintenance script, if no records met my criteria, I said goodbye with res.send() and had additional logic after it. I was expecting that piece not to be run, since I've already terminated the request.
Example producing unexpected results:
exports.someFunction = functions.https.onRequest((req, res) => {
if (exitCriteria === true) {
// we can exit the function, nothing to do
console.log('Exit criteria met')
res.status(200).send()
}
// code to handle if someCriteria was falsy
console.log('Exit criteria not met, continue executing code')
})
In the above example, I was expecting res.send() to terminate the function immediately - this is not so, the second console.log may also be hit - along with any other code you may have. This is not guaranteed, however, so execution may abruptly stop at some point.
Example producing correct results:
exports.someFunction = functions.https.onRequest((req, res) => {
if (exitCriteria === true) {
// we can exit the function, nothing to do
console.log('Exit criteria met')
res.status(200).send()
}
else {
// code to handle if someCriteria was falsy
console.log('Exit criteria not met, continue executing code')
}
})
In this version, you will see exactly 1 line of console.logs - as I was originally intending.

Firebase callable functions with background tasks [duplicate]

I'm using Firebase Functions with https triggers, and I was wondering how long after sending the response to the client, the functions keeps executing. I want to send a response to the client and then perform another operation (send a mail).
Currently I'm doing this as following:
module.exports.doSomeJob = functions.https.onRequest((req, res) => {
doSomeAsyncJob()
.then(() => {
res.send("Ok");
})
.then(() => {
emailSender.sendEmail();
})
.catch(...);
});
The above code is working for me, but I'm suspecting that the code only works because sending the mail has finished before the res.send has completed, so I was wondering how exactly the termination process is working to make sure the code will not break.
You should expect that the HTTP function terminates the moment after you send the response. Any other behavior is some combination of luck or a race condition. Don't write code that depends on luck.
If you need to send a response to the client before the work is fully complete, you will need to kick off a second function to continue where the HTTP function left off. It's common to use a pub/sub function to do with. Have the HTTP function send a pub/sub message to another function, then terminate the HTTP function (by sending a response) only after the message is sent.
If the expected response is not pegged to the outcome of the execution, then you can use
module.exports.doSomeJob = functions.https.onRequest((req, res) => {
res.write('SUCCESS')
return doSomeAsyncJob()
.then(() => {
emailSender.sendEmail();
})
.then(() => {
res.end();
})
.catch(...);
});
This sends back a response a soon as a request is received, but keeps the function running until res.end() is called
Your client can end the connection as soon as a response is received back, but the cloud function will keep running in the background
Not sure if this helps, but it might be a workaround where the client needs a response within a very limited time, considering that executing pub/sub requires some extra processing on its own and takes time to execute
TL;DR
While https functions will terminate shortly after res.send(), it is not guaranteed that 0 lines of code after res.send() will be executed.
I think a fuller answer has 2 components:
as Doug pointed out, do not put any additional code you expect to be executed after res.send()
cloud functions will terminate shortly after res.send(), but don't expect that exactly 0 lines of code will be executed
I ran into a situation where for a db maintenance script, if no records met my criteria, I said goodbye with res.send() and had additional logic after it. I was expecting that piece not to be run, since I've already terminated the request.
Example producing unexpected results:
exports.someFunction = functions.https.onRequest((req, res) => {
if (exitCriteria === true) {
// we can exit the function, nothing to do
console.log('Exit criteria met')
res.status(200).send()
}
// code to handle if someCriteria was falsy
console.log('Exit criteria not met, continue executing code')
})
In the above example, I was expecting res.send() to terminate the function immediately - this is not so, the second console.log may also be hit - along with any other code you may have. This is not guaranteed, however, so execution may abruptly stop at some point.
Example producing correct results:
exports.someFunction = functions.https.onRequest((req, res) => {
if (exitCriteria === true) {
// we can exit the function, nothing to do
console.log('Exit criteria met')
res.status(200).send()
}
else {
// code to handle if someCriteria was falsy
console.log('Exit criteria not met, continue executing code')
}
})
In this version, you will see exactly 1 line of console.logs - as I was originally intending.

Unhandled Rejection (SyntaxError): Unexpected token < in JSON at position 0?

I am trying to fetch local api made in asp.net api which is running in https://localhost:44388/. When I tried to fetch get request it responds ok but return html not json. The problem might occur by two reasons:
1.typo in url (But I checked in my browser, it worked)
2.Server restart needed
What might be the problem with my code?
componentDidMount(){
var proxyUrl = "http://127.0.0.1:3000/";
var targetUrl = "https://127.0.0.1:44388/api/product/getproducts";
fetch(proxyUrl+targetUrl, {
method:'GET',
headers:{
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Mehods': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Credentials':'*',
'Content-type':'application/json'
}
})
.then(data=>{
if(!data.ok){
throw new Error("Error");
}else{
return data.json();
}
})
.then(data=>this.setState({products:data}))
}
when you give parameter as:proxyUrl+targetUrl,
actually the url which you have called is :
http://127.0.0.1:3000/https://127.0.0.1:44388/api/product/getproducts
which does not seems to be correct.
i think the structure of url you'v given to fetch function is wrong.

Continue execution after sending response (Cloud Functions for Firebase)

I'm using Firebase Functions with https triggers, and I was wondering how long after sending the response to the client, the functions keeps executing. I want to send a response to the client and then perform another operation (send a mail).
Currently I'm doing this as following:
module.exports.doSomeJob = functions.https.onRequest((req, res) => {
doSomeAsyncJob()
.then(() => {
res.send("Ok");
})
.then(() => {
emailSender.sendEmail();
})
.catch(...);
});
The above code is working for me, but I'm suspecting that the code only works because sending the mail has finished before the res.send has completed, so I was wondering how exactly the termination process is working to make sure the code will not break.
You should expect that the HTTP function terminates the moment after you send the response. Any other behavior is some combination of luck or a race condition. Don't write code that depends on luck.
If you need to send a response to the client before the work is fully complete, you will need to kick off a second function to continue where the HTTP function left off. It's common to use a pub/sub function to do with. Have the HTTP function send a pub/sub message to another function, then terminate the HTTP function (by sending a response) only after the message is sent.
If the expected response is not pegged to the outcome of the execution, then you can use
module.exports.doSomeJob = functions.https.onRequest((req, res) => {
res.write('SUCCESS')
return doSomeAsyncJob()
.then(() => {
emailSender.sendEmail();
})
.then(() => {
res.end();
})
.catch(...);
});
This sends back a response a soon as a request is received, but keeps the function running until res.end() is called
Your client can end the connection as soon as a response is received back, but the cloud function will keep running in the background
Not sure if this helps, but it might be a workaround where the client needs a response within a very limited time, considering that executing pub/sub requires some extra processing on its own and takes time to execute
TL;DR
While https functions will terminate shortly after res.send(), it is not guaranteed that 0 lines of code after res.send() will be executed.
I think a fuller answer has 2 components:
as Doug pointed out, do not put any additional code you expect to be executed after res.send()
cloud functions will terminate shortly after res.send(), but don't expect that exactly 0 lines of code will be executed
I ran into a situation where for a db maintenance script, if no records met my criteria, I said goodbye with res.send() and had additional logic after it. I was expecting that piece not to be run, since I've already terminated the request.
Example producing unexpected results:
exports.someFunction = functions.https.onRequest((req, res) => {
if (exitCriteria === true) {
// we can exit the function, nothing to do
console.log('Exit criteria met')
res.status(200).send()
}
// code to handle if someCriteria was falsy
console.log('Exit criteria not met, continue executing code')
})
In the above example, I was expecting res.send() to terminate the function immediately - this is not so, the second console.log may also be hit - along with any other code you may have. This is not guaranteed, however, so execution may abruptly stop at some point.
Example producing correct results:
exports.someFunction = functions.https.onRequest((req, res) => {
if (exitCriteria === true) {
// we can exit the function, nothing to do
console.log('Exit criteria met')
res.status(200).send()
}
else {
// code to handle if someCriteria was falsy
console.log('Exit criteria not met, continue executing code')
}
})
In this version, you will see exactly 1 line of console.logs - as I was originally intending.

Resources