Version
vert.x core:3.5.0
vert.x redis client:3.5.0
Context
2018-06-02 17:40:55.981 ERROR 4933 --- [ntloop-thread-2] io.vertx.redis.impl.RedisConnection : No handler waiting for message: 14751915
2018-06-02 17:41:10.937 ERROR 4933 --- [ntloop-thread-2] io.vertx.redis.impl.RedisConnection : No handler waiting for message: false
2018-06-02 17:41:10.947 ERROR 4933 --- [ntloop-thread-2] io.vertx.redis.impl.RedisConnection : No handler waiting for message: false
2018-06-02 17:41:20.937 ERROR 4933 --- [ntloop-thread-2] io.vertx.redis.impl.RedisConnection : No handler waiting for message: true
2018-06-02 17:41:30.937 ERROR 4933 --- [ntloop-thread-2] io.vertx.redis.impl.RedisConnection : No handler waiting for message: true
2018-06-02 17:41:35.927 ERROR 4933 --- [ntloop-thread-2] io.vertx.redis.impl.RedisConnection : No handler waiting for message: false
2018-06-02 17:41:40.937 ERROR 4933 --- [ntloop-thread-2] io.vertx.redis.impl.RedisConnection : No handler waiting for message: true
2018-06-02 17:41:50.948 ERROR 4933 --- [ntloop-thread-2] io.vertx.redis.impl.RedisConnection : No handler waiting for message: true
After view code of the io.vertx.redis.impl.RedisConnectioni find the why:
When server started, create redis connetion,it's ok for runing.
After long time (eg.days),the state of connection is DISCONNECTED. Vert.x redis client reconnect redis server when send command to redis server:
void send(final Command command) {
// start the handshake if not connected
if (state.get() == State.DISCONNECTED) {
connect();
}
connect() call clearQueue()
clearQueue(): waiting command quene will be empty.
Call handleReply() when receive from redis server with new connection.
note: An error log appears here(the third line to bottom).
private void handleReply(Reply reply) {
final Command cmd = waiting.poll();
if (cmd != null) {
switch (reply.type()) {
case '-': // Error
cmd.handle(Future.failedFuture(reply.asType(String.class)));
return;
case '+': // Status
switch (cmd.responseTransform()) {
case ARRAY:
cmd.handle(Future.succeededFuture(new JsonArray().add(reply.asType(String.class))));
break;
default:
cmd.handle(Future.succeededFuture(reply.asType(cmd.returnType())));
break;
}
return;
case '$': // Bulk
switch (cmd.responseTransform()) {
case ARRAY:
cmd.handle(Future.succeededFuture(new JsonArray().add(reply.asType(String.class, cmd.encoding()))));
break;
case INFO:
String info = reply.asType(String.class, cmd.encoding());
if (info == null) {
cmd.handle(Future.succeededFuture(null));
} else {
String lines[] = info.split("\\r?\\n");
JsonObject value = new JsonObject();
JsonObject section = null;
for (String line : lines) {
if (line.length() == 0) {
// end of section
section = null;
continue;
}
if (line.charAt(0) == '#') {
// begin section
section = new JsonObject();
// create a sub key with the section name
value.put(line.substring(2).toLowerCase(), section);
} else {
// entry in section
int split = line.indexOf(':');
if (section == null) {
value.put(line.substring(0, split), line.substring(split + 1));
} else {
section.put(line.substring(0, split), line.substring(split + 1));
}
}
}
cmd.handle(Future.succeededFuture(value));
}
break;
default:
cmd.handle(Future.succeededFuture(reply.asType(cmd.returnType(), cmd.encoding())));
break;
}
return;
case '*': // Multi
switch (cmd.responseTransform()) {
case HASH:
cmd.handle(Future.succeededFuture(reply.asType(JsonObject.class, cmd.encoding())));
break;
default:
cmd.handle(Future.succeededFuture(reply.asType(JsonArray.class, cmd.encoding())));
break;
}
return;
case ':': // Integer
switch (cmd.responseTransform()) {
case ARRAY:
cmd.handle(Future.succeededFuture(new JsonArray().add(reply.asType(Long.class))));
break;
default:
cmd.handle(Future.succeededFuture(reply.asType(cmd.returnType())));
break;
}
return;
default:
cmd.handle(Future.failedFuture("Unknown message type"));
}
} else {
// **An error log appears here**
log.error("No handler waiting for message: " + reply.asType(String.class));
}
}
question:
It's a bug or not?
If not a bug , the post commands will be discarded when reconnect redis server.
What's a good way to deal with this situation?
The problem has been solved. The reason for the above problem is that the connection has been reused and has not been closed. The solution is:
`
RedisClient redisClient = RedisClient.create(this.vertx, redisOptions);
//do some thing;
redisClient.close(h-{})...
`
for each session.
Related
When using spring-cloud-stream for streaming application (functional style) with batches, is there a way to retry/DLQ a failed message but also process (stream) the non-failing records?
for example:
function received batch of 10 records, and attempts to convert them to other type and return the new records for producing. let's say record 8 failed on mapping, is it possible to complete the producing of records 0-7 and then retry/DLQ record 8?
throwing BatchListenerFailedException with the index does not cause the prior messages to be sent.
spring kafka version: 2.8.0
code:
#Override
public List<Message<Context>> apply(Message<List<Context>> listMessage) {
List<Message<Context>> output = new ArrayList<>();
IntStream.range(0, listMessage.getPayload().size()).forEach(index -> {
try {
Record<Context> record = Record.fromBatch(listMessage, index);
output.add(MessageBuilder.withPayload(record.getValue()).build());
if (index == listMessage.getPayload().size() - 1) {
throw new TransientError("offset " + record.getOffset() + "failed", new RuntimeException());
}
} catch (Exception e) {
throw new BatchListenerFailedException("Tigger retry", e, index);
}
});
return output;
}
customizer:
private CommonErrorHandler getCommonErrorHandler(String group) {
DefaultErrorHandler errorHandler = new DefaultErrorHandler(getRecoverer(group), getBackOff());
errorHandler.setLogLevel(KafkaException.Level.DEBUG);
errorHandler.setAckAfterHandle(true);
errorHandler.setClassifications(Map.of(
PermanentError.class, false,
TransientError.class, true,
SerializationException.class, properties.isRetryDesErrors()),
false);
errorHandler.setRetryListeners(getRetryListener());
return errorHandler;
}
private ConsumerRecordRecoverer getRecoverer(String group) {
KafkaOperations<?, ?> operations = new KafkaTemplate<>(new DefaultKafkaProducerFactory<>(producerProperties()));
DeadLetterPublishingRecoverer recoverer = new DeadLetterPublishingRecoverer(
operations, getDestinationResolver(group));
recoverer.setHeadersFunction(this::buildAdditionalHeaders);
return recoverer;
}
yaml:
spring:
cloud:
function:
definition: batchFunc
stream:
default-binder: kafka-string-avro
binders:
kafka-string-avro:
type: kafka
environment.spring.cloud.stream.kafka.binder.consumerProperties:
key.deserializer: org.springframework.kafka.support.serializer.ErrorHandlingDeserializer
value.deserializer: org.springframework.kafka.support.serializer.ErrorHandlingDeserializer
spring.deserializer.key.delegate.class: org.apache.kafka.common.serialization.StringDeserializer
spring.deserializer.value.delegate.class: io.confluent.kafka.serializers.KafkaAvroDeserializer
schema.registry.url: ${SCHEMA_REGISTRY_URL:http://localhost:8081}
value.subject.name.strategy: io.confluent.kafka.serializers.subject.TopicNameStrategy
specific.avro.reader: true
environment.spring.cloud.stream.kafka.binder.producerProperties:
key.serializer: org.apache.kafka.common.serialization.StringSerializer
value.serializer: io.confluent.kafka.serializers.KafkaAvroSerializer
schema.registry.url: ${SCHEMA_REGISTRY_URL:http://localhost:8081}
value.subject.name.strategy: io.confluent.kafka.serializers.subject.TopicNameStrategy
bindings:
batchFunc-in-0:
binder: kafka-string-avro
destination: records.publisher.output
group: function2-in-group
contentType: application/*+avro
consumer:
batchMode: true
function2-out-0:
binder: kafka-string-avro
destination: reporter.output
producer:
useNativeEncoding: true
kafka:
binder:
brokers: ${KAFKA_BROKER_ADDRESS:localhost:9092}
autoCreateTopics: ${KAFKA_AUTOCREATE_TOPICS:false}
default:
consumer:
startOffset: ${START_OFFSET:latest}
enableDlq: false
default:
consumer:
maxAttempts: 1
defaultRetryable: false
I am working on a BLE Scanner.Basically I am looking for an iBeacon device with 0x4c type and a payload size of 30. However when i run this mbed crashes after spitting out few print lines. This code is very hit and miss.
it is getting an index out of bound error(understandably). How do I catch the error and skip it?
void Scanner::onAdvertisingReport(const AdvertisingReportEvent &event)
{
printf("Looking for Devices\r\n");
AdvertisingDataParser adv_data(event.getPayload());
while(adv_data.hasNext())
{
if (event.getPayload().size() == 30 and event.getPayload()[5] == 0x4c)
{
beacon_found = true;
while(beacon_found)
{
printf("Found Beacon!\r\n");
::print_address(event.getPeerAddress());
printf("RSSI : %d\r\n",event.getRssi());
printf("PL: %d\r\n",event.getPayload().size());
printf("Major Value: %d\r\n",event.getPayload()[26]);
printf("Minor Value: %d\r\n",event.getPayload()[27]);
break;
}
beacon_found = false;
break;
}
else
{
printf("Couldnt find beacon!\r\n");
break;
}
}
adv_data.next();
}
Error:
Error Status: 0x80FF0140 code 324 module 255
Assertion failed: 0 <= index && index < _size in Span.h
Trying to make TCP connection with Google mail server through IMAP protocol with "Network framework" (Swift), but I got an error.
I got code from this (wwdc2018) video.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let connection = NWConnection(host: "imap.google.com", port: .imaps, using: .tls)
let myQueue = DispatchQueue(label: "test")
connection.stateUpdateHandler = { (newState) in
switch (newState) {
case .waiting(let error):
print("ERROR - \(error)")
case .preparing:
print("I am HERE")
case .ready:
print("HELLO")
case .failed(let error):
print("ERROR + \(error)")
default:
break
}
}
connection.start(queue: myQueue)
return true
}
My console displays:
I am HERE
ERROR - -65554: NoSuchRecord
UDPATED:
Thanks to #arnt I remembered that host must be "imap.gmail.com", now works fine!
The main goal is to create TCP connection with Google mail server through IMAP protocol with "Network framework", but on Objective-C.
I tried it myself and I succeeded! =)
const char *hostname = "imap.gmail.com";
const char *port = "imaps";
nw_parameters_t parameters = nw_parameters_create_secure_tcp(NW_PARAMETERS_DEFAULT_CONFIGURATION, NW_PARAMETERS_DEFAULT_CONFIGURATION);
nw_endpoint_t endpoint = nw_endpoint_create_host(hostname, port);
nw_connection_t connection = nw_connection_create(endpoint, parameters);
nw_connection_set_queue(connection, dispatch_get_main_queue());
nw_connection_set_state_changed_handler(connection, ^(nw_connection_state_t state, nw_error_t error) {
switch (state) {
case nw_connection_state_waiting:
NSLog(#"waiting");
break;
case nw_connection_state_failed:
NSLog(#"failed");
break;
case nw_connection_state_ready:
NSLog(#"connection is ready");
break;
case nw_connection_state_cancelled:
NSLog(#"connection is cancelled");
break;
default:
break;
}
});
nw_connection_start(connection);
I have the below cloud code function and when I call this function from my OS X app, I get the success response as well. But none of the console log output messages inside the success and failure blocks of the query operation gets executed. Any ideas on where to look would be much appreciated.
Parse.Cloud.define("markAlertAsExpired", function(request, response) {
Parse.Cloud.useMasterKey();
var Alert = Parse.Object.extend("Alert");
var query = new Parse.Query(Alert);
query.get("vC6ppoxuqd", {
success: function(alertObj) {
// The object was retrieved successfully.
var status = alertObj.get("status");
console.log("RECEIVED OBJECT WITH STATUS:");
console.log(status);
if (status == "active") {
console.log("active");
markActiveAlertAsExpired(alertObj);
} else if (status == "inactive") {
console.log("inactive");
markInactiveAlertAsExpired(alertObj);
} else {
console.error("unknown_status");
}
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
console.error("alert_not_found");
response.error("alert_not_found");
}
});
response.success("available");
});
You need to wait for your queries to complete before calling response.success, the updated code below should work.
Parse.Cloud.define("markAlertAsExpired", function(request, response) {
Parse.Cloud.useMasterKey();
var Alert = Parse.Object.extend("Alert");
var query = new Parse.Query(Alert);
query.get("vC6ppoxuqd", {
success: function(alertObj) {
// The object was retrieved successfully.
var status = alertObj.get("status");
console.log("RECEIVED OBJECT WITH STATUS:");
console.log(status);
if (status == "active") {
console.log("active");
markActiveAlertAsExpired(alertObj);
} else if (status == "inactive") {
console.log("inactive");
markInactiveAlertAsExpired(alertObj);
} else {
console.error("unknown_status");
}
response.success("available");
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
console.error("alert_not_found");
response.error("alert_not_found");
}
});
});
The program runs fine when the user is connected to the internet. However, when the user is not connected, the app crashes with:
Error:The operation couldn’t be completed. (kCLErrorDomain error 8.)
fatal error: unexpectedly found nil while unwrapping an Optional value
I'd like the catch the error before it crashes and display an alertcontroller
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: { (placemarks, error) -> Void in
if (error != nil) {
println("Error:" + error.localizedDescription)
}
if placemarks.count > 0 {
let pm = placemarks[0] as CLPlacemark
self.displayLocationInfo(pm)
currentLoc = manager.location
currentLocGeoPoint = PFGeoPoint(location:currentLoc)
var query = PFQuery(className:"Restaurant") //default: Restaurant
query.whereKey("RestaurantLoc", nearGeoPoint:currentLocGeoPoint, withinMiles:setDistanceMiles) //filter by miles
query.limit = 1000 //limit number of results
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if objects.isEmpty {
//NO RESULTS
let alertController = UIAlertController(title: "Unavailable Area", message:
"This app is not available in your area yet. We'll try our best to have it up and running as soon as possible.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
self.navigationController!.popViewControllerAnimated(true)
} else {
newArray = objects
}
self.hideActivityIndicator(self.view)
}
} else {
println("error: \(error)")
}
})
}
The problem is your if statement. You are saying this:
if (error != nil) {
println("Error:" + error.localizedDescription)
}
if placemarks.count > 0 { // ...
Well, there was an error. And you were told that there was an error. But you didn't listen! You didn't stop! You just go right on as if nothing had happened, and try to access the placemarks variable - which wasn't returned. You need to use logic here so that you exit if there's an error:
if (error != nil) {
println("Error:" + error.localizedDescription)
return // go no further!
}
if placemarks.count > 0 { // ...
Note, however, that it would be better to check placemarks for nil first:
if placemarks == nil {
// check error
// return
}
if placemarks.count > 0 { // ...
I believe you need to implement locationManager:didFailWithError which tells the delegate when it is unable to retrieve the location. Then, you just need to handle the error with appropriate response.
For references: CLLocationManagerDelegate apple docs