Handle Nancy error in OnError or OnError.AddItemToEndOfPipeline? - nancy

The Nancy documentation says that you can use pipelines.OnError += (x, y) =>... to handle errors, but I have seen some tutorials using pipelines.OnError.AddItemToEndOfPipeline((x, y) =>....
Both seem to result in the error being handled correctly. Is there an actual difference between the two?

No pipelines.OnError += (x ,y) => ... adds the handler to the end of the pipeline, just like pipelines.OnError.AddItemToEndOfPipeline((x, y) => ..) does.
See the source code: https://github.com/NancyFx/Nancy/blob/master/src/Nancy/ErrorPipeline.cs#L39

Related

how to check if string exist in list of strings in Gatling Scala

How to check if ponkipong is present in activeids using [Gatling] check - [Scala] ?
{
"activeids": [
"ironblossom",
"draw_on",
"ponkipong",
"summer22",
"morphimagus"
]
}
Have tried .check(jmesPath("activeids[?contains(#, 'ponkipong') == `true`]").transform(_.length >= 1).is(true)) but
doesn't work.
Also not sure how to do this using jsonPath.
Though, Kind of a workaround I am currently using is this.
.check(bodyString.saveAs("response_data"))
.check(
checkIf((response: Response, session: Session) => {
val dde = "ponkipong"
val is_dde_active_not_present = if ((Json.parse(session("response_data").as[String].stripMargin) \ "activeids").as[Seq[String]].indexOf(dde) >= 0) false else true
is_dde_active_not_present
}) {
// this check is to make forceful fail if checkIf fails
jsonPath("$.activeids[*]").count.is(-1)
}
)
But, doesn’t look like a solution.
Need help to do it in a proper way.
Nowadays, I tend to use JMESPath whenever possible, as explained here.
In Scala:
jmesPath("contains(activeids, 'ponkipong')").ofType[Boolean].is(true)
In Java (recommended since Gatling 3.7):
jmesPath("contains(activeids, 'ponkipong')").ofBoolean().is(true)

How to convert a UUID string into UUID type

I have an array of string UUIDs that I want to change to UUID. Example of the data:
["69359037-9599-48e7-b8f2-48393c019135" "1d8a7307-b5f8-4686-b9dc-b752430abbd8"]
How can I change or parse it? I tried using uuid.fromString() method:
if len(a) == 2 {
user1 := a[0]
a[0], _ = uuid.FromString(a[0])
}
However, this gives me an error
FromString returns UUID parsed from string input. Input is expected in
a form accepted by UnmarshalText.
With github.com/gofrs/uuid/v5, use uuid.FromString.
FromString returns UUID parsed from string input. Input is expected in a form accepted by UnmarshalText.
This method returns UUID or an error in case the parsing failed. You have two options to avoid explicit error handling:
FromStringOrNil, which returns only a UUID, but possibly nil in case of error
Must, which panics when the error of FromString is not nil. You use like:
uuid.Must(uuid.FromString("69359037-9599-48e7-b8f2-48393c019135"))
WARNING: satori/go.uuid, the older popular UUID package, nowadays is unmaintained and has unfixed issues. The package gofrs/uuid mentioned above is a maintained fork. From the package documentation:
We recommend using v2.0.0+ of this package, as versions prior to 2.0.0 were created before our fork of the original package and have some known deficiencies.
With github.com/google/uuid, use uuid.Parse. The rest of the pattern is the same as satori/uuid.
In your specific case, it looks like there's no problem in parsing the UUIDs, however the code you posted doesn't seem to produce the error you mention. Instead there is another problem:
a[0], _ = uuid.FromString(a[0])
you are attempting to reassign the value of uuid.FromString, which is a UUID to a[0] which is, presumably, a string.
The following code works fine (see it on Go Play):
var a = []string{"69359037-9599-48e7-b8f2-48393c019135", "1d8a7307-b5f8-4686-b9dc-b752430abbd8"}
func main() {
if len(a) == 2 {
user1 := a[0]
s, _ := uuid.FromString(a[0])
fmt.Println(user1) // prints 69359037-9599-48e7-b8f2-48393c019135
fmt.Println(s) // prints 69359037-9599-48e7-b8f2-48393c019135
}
}

Summing the values of multiple Vectors in the session

In my gatling scenario, I need to check the session for a few entries that will be Vectors of numbers. I can get the Vectors if present, but when I attempt to add them using .sum I get a ClassCastException stating that java.lang.String can't be cast to java.lang.Integer
I've debugged by printing out the value retrieved from the session (Vector(100,200,300)), and even confirmed that the individual elements are Ints. However when I try to add any of them, either with something like values.sum or values(0)+values(1) I get the class cast exception
I'm setting values in the session with checks like
.check(jsonPath("$..payments..paymentAmount").findAll.optional.saveAs("payments"))
.check(jsonPath("$..receipts..receiptAmount").findAll.optional.saveAs("receipts"))
in my app these will always result in things like Vector(100, 200, 300) if the path was there
then later I want to sum all the values in these lists so I have the action
.exec(session => {
def addAmounts(listNames: Array[String]): Int = {
listNames.foldLeft(0)((acc, listName) => {
session(listName).validate[Seq[Int]] match {
case Success(ints) => ints.sum + acc
case Failure(error) => acc
}})
}
val transactionsTotal = addAmounts(Array("payments", "receipts"))
session.set("total",transactionsTotal)
}
As mentioned, this fails on the listName.sum + acc statement - since they're both Ints I'd expect there'd be no need to cast from a string
The Failure case where nothing was stored from the check works fine
I think this is a scala type inference issue - I got it working by manually casting to Int before doing addition

Why is my Observable only sending a message to the most recent subscriber

I have 2 Angular (1.6.4) components and a service. The service creates 2 observables like this (coffeescript)...
// In service constructor
#observable = Rx.Observable.create (source) =>
source.next(123)
#observable2 = Rx.Observable.create (source) =>
#observer = source
$timeout =>
#observer.next(345)
, 1000
In my controllers I have these lines
//Component 1
service.observable.subscribe (v) => console.log('consumer A1: ' + v)
service.observable2.subscribe (v) => console.log('consumer A2: ' + v)
//Component 2
service.observable.subscribe (v) => console.log('consumer B1: ' + v)
service.observable2.subscribe (v) => console.log('consumer B2: ' + v)
I would expect to see 4 console logs but instead I see 3 (A1, B1, B2). Why is it then when I call from outside only the last subscribe gets called but when it is inside both get called? Is there a way to have the second example call both (preferably as an Observable and not a Subject)?
If I do use a Subject everything works as expected but I am still curious why it doesn't work as I would expect with an observable.
Your observable2 is taking the subscriber and storing it in a variable (#observer) each time something subscribes. So the 2nd subscription (B2) is replacing the value in the variable.
It is hard to say what the correct way to rewrite the 2nd observer should be because it isn't clear what your goal is. A Subject can certainly work. Observable.timer might also work, depending on your goal.
The Observable.timer way would be:
#observable2 = Observable.timer(1000);
Anything that subscribes to that would get an event 1 second after it subscribed.

Discriminated union method doesn't see its static member

The problem seems to be dumb, but I really don't get it.
module Responses =
type Failure =
| Problem of string
| Error of exn
| Timeout
static member toString x =
match x with
| Problem str -> sprintf "Problem %s" str
| Error e -> sprintf "Error %s" (e.ToString())
| Timeout -> "Timeout"
override x.ToString() = Failure.toString x
error is
override x.ToString() = Failure.toString x;;
--------------------------------------^^^^^^^^
stdin(11,41): error FS0039: The field, constructor or member 'toString' is not defined
Reason is that f# for some reason thinks that Failure is of type Microsoft.FSharp.Core.Operations.Failure
When I try to write
override x.ToString() = Responses.Failure.toString x
I get
Startup.fs(14,33): error FS0039: The namespace or module 'Responses' is not defined
When I rename Failure to for example xFailure, it works. But I really do not want to rename it. Can I somehow avoid renaming and use static method?
This is a bit surprising behavior! I think it is happening because Failure is another type that is defined in the F# core library. When you try calling the static method, the compiler (for some reason) picks only the F# library type, but does not union the static methods (which is what I would expect).
I think it might be a bug - so please report it on the F# CodePlex site.
As a workaround, I only came up with a fairly ugly idea, which is to define a private type alias such as FailureStatic and then use the alias to call static members (the users of your library will not see it).
module Responses =
type private FailureStatic = Failure
and Failure =
| Problem of string
| Error of exn
| Timeout
static member toString x =
match x with
| Problem str -> sprintf "Problem %s" str
| Error e -> sprintf "Error %s" (e.ToString())
| Timeout -> "Timeout"
override x.ToString() = FailureStatic.toString x

Resources