How do I handle a failed post operation using Giraffe? - asp.net-web-api

How do I handle a failed post operation using Giraffe?
What's the recommended practice for a failed post operation using Giraffe?
let private registrationHandler =
fun(context: HttpContext) ->
async {
let! data = context.BindJson<RegistrationRequest>()
let response = register data |> function
| Success profile -> profile
| Failure -> ???
return! json response context
}
Specifically, if the server fails to write data to some database, what should I return to the client (that will compile).

The handler has to return something, but it doesn't always have to be the same serialized object. I've only had a quick glance at Giraffe, but using similar approach from Suave with Giraffe's examples here: https://github.com/dustinmoris/Giraffe#setstatuscode, I would do something like this:
type ErrorResponse = { message: string; ... }
let private registrationHandler =
fun(context: HttpContext) ->
async {
let! data = context.BindJson<RegistrationRequest>()
match register data with
| Success profile ->
return! json profile context
| Failure ->
let response = { message = "registration failed"; ... }
return! (setStatusCode 500 >=> json response) context
}

Related

Why can't subscribe the request in reactor-netty?

I just want access the Http content in reactor-netty project. But the result is null.
Code is below.
DisposableServer server =
HttpServer.create()
.host("localhost")
.port(8000)
.route(routes ->
.post("/echo",
(request, response) ->
{ request.receive()
.retain()
.aggregate()
.asString()
.subscribe(System.out::println);
return response.sendString(Mono.just("hello"));})
.bindNow();
I can't get the rerult in the console.
Could I access the request as what I do in the code?
Anyone can help? Thanks.
You return the response before the request data is received, so Reactor Netty will drop any incoming data that is received AFTER the response is sent.
I don't know your use case but changing the example to this below, you will be able to see the incoming data:
DisposableServer server =
HttpServer.create()
.host("localhost")
.port(8000)
.route(routes ->
routes.post("/echo",
(request, response) ->
response.sendString(request.receive()
.retain()
.aggregate()
.asString()
.flatMap(s -> {
System.out.println(s);
return Mono.just("hello");
})))
)
.bindNow();

How can i handle connection and reconnect if connection got closed?

I need this client stay connected for long, How can i make sure about connection? because the issue was in connection, so i am updating my question. what should i do if server close connection? or if client close connection? how can i handle it and reconnect client to the server?
public void consumeServerSentEvent() {
WebClient client = WebClient.create("http://localhost:8080/sse-server");
ParameterizedTypeReference<ServerSentEvent<String>> type
= new ParameterizedTypeReference<ServerSentEvent<String>>() {};
Flux<ServerSentEvent<String>> eventStream = client.get()
.uri("/stream-sse")
.retrieve()
.bodyToFlux(type);
eventStream.subscribe(
content -> logger.info("Time: {} - event: name[{}], id [{}], content[{}] ",
LocalTime.now(), content.event(), content.id(), content.data()),
error -> logger.error("Error receiving SSE: {}", error),
() -> logger.info("Completed!!!"));
}
According to documentation retrieve() returns Mono of ClientResponse, but for your case you need to consume Flux of the body.
Try some thing like this:
Flux<ServerSentEvent<String>> eventStream = client.get()
.uri("/stream-sse")
.retrieve()
.flatMapMany(response -> response.bodyToFlux(type));

Customizing the criteria for triggering Fallback in Hystrix Circuit Breaker

I would like to trigger a fallback from a #HystrixCommand Method based on my own criteria (checking for a specific response status).
My method basically acts as a client which calls a service in another URL (marked here as URL).
Here is my code:
#HystrixCommand(fallbackMethod="fallbackPerformOperation")
public Future<Object> performOperation(String requestString) throws InterruptedException {
return new AsyncResult<Object>() {
#Override
public Object invoke() {
Client client = null;
WebResource webResource = null;
ClientResponse response =null;
String results = null;
try{
client = Client.create();
webResource = client.resource(URL);
client.setConnectTimeout(10000);
client.setReadTimeout(10000);
response = webResource.type("application/xml")
.post(ClientResponse.class, requestString);
logger.info("RESPONSE STATUS: " + response.getStatus());
if (response.getStatus() != 200) {
webResource = null;
logger.error(" request failed with the HTTP Status: " + response.getStatus());
throw new RuntimeException(" request failed with the HTTP Status: "
+ response.getStatus());
}
results = response.getEntity(String.class);
} finally {
client.destroy();
webResource = null;
}
return results;
}
};
}
This triggers the fallback Method fallbackPerformOperation() when the response status code is not 200 i.e. response.getStatus()!=200.
The fallback method returns a string which tells the user that the Request did not return a status of 200 and so it is falling back.
I want to know if I can trigger the fallback without having to explicitly throw an exception inside my performOperation() Method.
Could I use #HystrixProperty? I know people mostly use it for timeouts and volume thresholds but could I write a custom #HystrixProperty that checks if the response status is 200 or not within my Method?

How to emit error when get json with key

I'm using RxAlamorefire to handle network task in my app.
My problem is: When I make a request and it return json. If json has a key "error" I need emit error notification instead of onNext notification.
My code is like this one:
let observable = RxAlamofire.json(.get, url, parameters: nil, encoding: URLEncoding.default, headers: header)
.map { (json) -> SomeObject? in
//Should check json maybe not in ".map" to see if the json contain "error" then emit onError notification.
return Mapper<SomeObject>().map(JSONObject: json)
}
Within map, you can use the throw keyword to send out and error
let observable = request.map { (json) -> SomeObject in
if let error = json["error"] as? [AnyHashable: Any] {
throw Mapper<ErrorObject>().map(JSONObject: error)
} else {
// regular deserialization
}
}
This will result in an observable emitting an error of type ErrorObject when the json contains the error key.

calling a method inside async callback

I am using kafka in my project using kafka-node package...
I have introduced a method and inside it i am trying to use a kafka module for eg:
Meteor.methods
kafka: (topic, message) ->
if(Meteor.isServer)
message = JSON.stringify(message)
kafka = Meteor.npmRequire 'kafka-node'
HighLevelProducer = kafka.HighLevelProducer
Client = kafka.Client
client = new Client
producer = new HighLevelProducer(client)
payloads =[{topic: topic, messages: [message]}]
producer.on 'ready', ->
producer.send payloads, (error,data) ->
if not error
HighLevelConsumer = kafka.HighLevelConsumer
Client = kafka.Client
client = new Client('localhost:2181')
topics = [ { topic: topic } ]
options =
autoCommit: true
fetchMaxWaitMs: 1000
fetchMaxBytes: 1024 * 1024
consumer = new HighLevelConsumer(client, topics, options)
consumer.on 'message',(message) ->
console.log message.value
#Meteor.call 'saveMessage', message.value, (error,data) ->
return
consumer.on 'error', (err) ->
console.log 'error', err
return
producer.on 'error', (err) ->
console.log 'error', err
Everything was fine until i decided to use meteor.call and call a method to save that message..
It gives me this error.
Meteor code must always run within a Fiber. Try wrapping callbacks
that you pass to non-Meteor libraries with Meteor.bindEnvironment
I tried encapsulating it inside Fiber, used Meteor.wrapAsync(), Neither helped,
Please guys can you help me, i am having difficult time solving this issue...
If you're using node style callbacks, you can use Meteor.bindEnvironment around the callback. For example:
let Sockets = new Mongo.Collection('connections');
function createConnection (name) {
check(name, String);
let socket = net.connect(23, '192.168.1.3', Meteor.bindEnvironment(function () {
Sockets.upsert({ name: name }, { $set: { status: 'connected' } });
}));
}

Resources