Does commitOffsets on high-level consumer block? - apache-kafka

In the Java Client (http://kafka.apache.org/documentation.html#highlevelconsumerapi), does commitOffsets on the high-level consumer block until offsets are successfully commited, or is it fire-and-forget?

Does commitOffsets on the high-level consumer block until offsets are successfully committed?
It looks like commitOffsets() loops through each consumer and calls updatePersistentPath if its offset has changed, and if so writes data via zkClient.writeData(path, getBytes(data)). It appears is though commitOffsets() does block until all the offsets are committed.
Here is the source code for commitOffsets() (ref):
public void commitOffsets() {
if (zkClient == null) {
logger.error("zk client is null. Cannot commit offsets");
return;
}
for (Entry<String, Pool<Partition, PartitionTopicInfo>> e : topicRegistry.entrySet()) {
ZkGroupTopicDirs topicDirs = new ZkGroupTopicDirs(config.getGroupId(), e.getKey());
for (PartitionTopicInfo info : e.getValue().values()) {
final long lastChanged = info.getConsumedOffsetChanged().get();
if (lastChanged == 0) {
logger.trace("consume offset not changed");
continue;
}
final long newOffset = info.getConsumedOffset();
//path: /consumers/<group>/offsets/<topic>/<brokerid-partition>
final String path = topicDirs.consumerOffsetDir + "/" + info.partition.getName();
try {
ZkUtils.updatePersistentPath(zkClient, path, "" + newOffset);
} catch (Throwable t) {
logger.warn("exception during commitOffsets, path=" + path + ",offset=" + newOffset, t);
} finally {
info.resetComsumedOffsetChanged(lastChanged);
if (logger.isDebugEnabled()) {
logger.debug("Committed [" + path + "] for topic " + info);
}
}
}
}
}
and for updatePersistentPath(...) (ref):
public static void updatePersistentPath(ZkClient zkClient, String path, String data) {
try {
zkClient.writeData(path, getBytes(data));
} catch (ZkNoNodeException e) {
createParentPath(zkClient, path);
try {
zkClient.createPersistent(path, getBytes(data));
} catch (ZkNodeExistsException e2) {
zkClient.writeData(path, getBytes(data));
}
}
}

Related

Respond from Volley library comes in twice

I am trying to figure out why a response from the Volley library comes in twice (and it is not always the same response that is doubled).
This is the result, a pie chart:
As we can see the total income and the total spending comes in twice (and if I debug it, it is never 4 GET calls, it is always at least 6 GET calls, although only 4 methods are executed).
Here is my code where I am trying to execute 4 GET requests.
public void initialize() {
getOutputFromDatabase(StaticFields.INCOME);
getOutputFromDatabase(StaticFields.EXPENSE);
getOutputFromDatabase(StaticFields.SAVINGS);
getOutputFromDatabase(StaticFields.FOOD);
}
private void getOutputFromDatabase(String incomeOrExpenseOrSavingsOrFood) {
//RequestQueue initialized
mRequestQueue = Volley.newRequestQueue(this);
// REST URL
String url = null;
if(incomeOrExpenseOrSavingsOrFood.equals("income")) {
url = StaticFields.PROTOCOL +
sharedPref_IP +
StaticFields.COLON +
sharedPref_Port +
StaticFields.REST_URL_GET_SUM_INCOME;
} else if (incomeOrExpenseOrSavingsOrFood.equals("expense")) {
url = StaticFields.PROTOCOL +
sharedPref_IP +
StaticFields.COLON +
sharedPref_Port +
StaticFields.REST_URL_GET_SUM_EXPENSE;
} else if (incomeOrExpenseOrSavingsOrFood.equals("savings")) {
url = StaticFields.PROTOCOL +
sharedPref_IP +
StaticFields.COLON +
sharedPref_Port +
StaticFields.REST_URL_GET_SUM_SAVINGS;
} else if (incomeOrExpenseOrSavingsOrFood.equals("food")) {
url = StaticFields.PROTOCOL +
sharedPref_IP +
StaticFields.COLON +
sharedPref_Port +
StaticFields.REST_URL_GET_SUM_FOOD;
}
//String Request initialized
StringRequest mStringRequest = new StringRequest(Request.Method.GET,
url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject obj = new JSONObject(response);
JSONArray jsonArray = new JSONArray();
jsonArray.put(obj);
JSONObject locs = obj.getJSONObject("incomeexpense");
JSONArray recs = locs.getJSONArray("Total income");
String repl = recs.getString(0);
if(incomeOrExpenseOrSavingsOrFood.equals("income") && repl.equals("null")) {
totalIncome.setText("0");
} else if(incomeOrExpenseOrSavingsOrFood.equals("income") && !repl.equals("null")){
totalIncome.setText(repl);
pieChart.addPieSlice(
new PieModel(
"Total income",
Float.parseFloat(repl),
Color.parseColor("#99CC00")));
} else if(incomeOrExpenseOrSavingsOrFood.equals("expense") && repl.equals("null")) {
totalExpense.setText("0");
} else if(incomeOrExpenseOrSavingsOrFood.equals("expense") && !repl.equals("null")) {
totalExpense.setText(repl);
pieChart.addPieSlice(
new PieModel(
"Total spending",
Float.parseFloat(repl),
Color.parseColor("#FF4444")));
} else if(incomeOrExpenseOrSavingsOrFood.equals("savings") && repl.equals("null")) {
totalSavings.setText("0");
} else if(incomeOrExpenseOrSavingsOrFood.equals("savings") && !repl.equals("null")) {
totalSavings.setText(repl);
pieChart.addPieSlice(
new PieModel(
"Total savings",
Float.parseFloat(repl),
Color.parseColor("#33B5E5")));
} else if(incomeOrExpenseOrSavingsOrFood.equals("food") && repl.equals("null")) {
totalFood.setText("0");
} else if(incomeOrExpenseOrSavingsOrFood.equals("food") && !repl.equals("null")) {
totalFood.setText(repl);
pieChart.addPieSlice(
new PieModel(
"Food/day",
Float.parseFloat(repl),
Color.parseColor("#FFBB33")));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i(TAG,"Error :" + error.toString());
}
});
mStringRequest.setShouldCache(false);
DefaultRetryPolicy retryPolicy = new DefaultRetryPolicy(5000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
mStringRequest.setRetryPolicy(retryPolicy);
mRequestQueue.add(mStringRequest);
// To animate the pie chart
pieChart.startAnimation();
}
Maybe someone know what I am doing wrong here?
I tried different things like
disabling the cache
setting a policy
but nothing worked so far.
I found my error.
The problem is that I am calling my methods where we can find the REST API calls in onResume again.
I had in my mind that onResume is called when someone comes back to his Activity, but I was wrong.
This is my right onResume now.
#Override
protected void onResume() {
super.onResume();
// pieChart.clearChart();
loadSharedPreferences(StaticFields.SP_PORT);
loadSharedPreferences(StaticFields.SP_INTERNET_ADDRESS);
loadSharedPreferences(StaticFields.SP_PERSON);
// getOutputFromDatabase(StaticFields.INCOME);
// getOutputFromDatabase(StaticFields.EXPENSE);
// getOutputFromDatabase(StaticFields.SAVINGS);
// getOutputFromDatabase(StaticFields.FOOD);
// To animate the pie chart
pieChart.startAnimation();
resetEditText();
}

How to unregister two vertx consumers and returns an rxjava completable?

I need a small help with Rxjava . currently I have two hash maps . Each hash map contains vertex message consumers against a subscription key. I want to return a completable object only if I am able to unregister both vertex message consumers. How can I achieve it .
I can post the code i am working on.
#Override
public Completable deregisterKeyEvents(String subscriptionId) {
MessageConsumer<JsonObject> messageConsumer = consumerMap.get(subscriptionId);
MessageConsumer<JsonObject> subscriptionConsumer = subscriptionConsumerMap.get(subscriptionId);
if( subscriptionConsumer != null) {
subscriptionConsumerMap.remove(subscriptionId);
subscriptionConsumer.unregister( res-> {
if(res.succeeded()) {
LOGGER.debug("Subscription channel consumer deregistered successfully!");
} else {
LOGGER.error("Unable to de-register Subscription channel consumer");
}
});
}
if (messageConsumer != null) {
consumerMap.remove(subscriptionId);
return Completable.create(emitter -> {
messageConsumer.unregister(res -> {
if (res.succeeded()) {
emitter.onComplete();
} else {
emitter.onError(res.cause());
}
});
});
} else {
LOGGER.warn("There was no consumer registered!");
return Completable.create(emitter -> emitter.onError(new KvNoSuchElementException("Subscription '" + subscriptionId + "' not found")));
}
}
I want to rewrite the above code in such a way
subscriptionConsumer.unregister() & messageConsumer.unregister() is successful then return a completable
The MessageConsumer class is from vert.x libary io.vertx.core.eventbus.MessageConsumer.
appreciate if you can help
thank you
If you're willing to add Vert.x RxJava2 to your dependencies, you could do this with toCompletable:
#Override
public Completable deregisterKeyEvents(String subscriptionId) {
MessageConsumer<JsonObject> messageConsumer = consumerMap.get(subscriptionId);
MessageConsumer<JsonObject> subscriptionConsumer = subscriptionConsumerMap.get(subscriptionId);
Completable c1;
if( subscriptionConsumer != null) {
subscriptionConsumerMap.remove(subscriptionId);
c1 = CompletableHelper.toCompletable(handler -> subscriptionConsumer.unregister(handler))
.doOnSuccess(() -> LOGGER.debug("Subscription channel consumer deregistered successfully!"))
.doOnError(t-> LOGGER.error("Unable to de-register Subscription channel consumer", t));
} else {
c1 = Completable.complete();
}
Completable c2;
if (messageConsumer != null) {
consumerMap.remove(subscriptionId);
c2 = CompletableHelper.toCompletable(handler -> messageConsumer.unregister(handler));
} else {
LOGGER.warn("There was no consumer registered!");
c2 = Completable.error(new KvNoSuchElementException("Subscription '" + subscriptionId + "' not found"));
}
return c1.concatWith(c2);
}
Note that this is a bit different than your original code because:
the messageConsumer unregistration happens only after the unregistration of subscriptionConsumer,
the messageConsumer unregistration happens only if unregistration of subscriptionConsumer was successful.
You can use a different method of Completable if that's not the behavior you want.

Apache commons net FTP clients hangs unpredictably

We tried all the solutions provided in this post (FTP client hangs) but none of them is working. We are using version 3.6 of commons net. Sometimes it hangs while uploading a file, sometimes will checking existence of a directory. Max. file size is around 400 MB. But sometime it hangs even for a small file size < 1KB. Below is the fragment of code:
public boolean uploadData(String inputFilePath, String destinationFolderName) {
if (StringUtil.isNullOrBlank(inputFilePath) || StringUtil.isNullOrBlank(destinationFolderName)) {
LOGGER.error("Invalid parameters to uploadData. Aborting...");
return false;
}
boolean result = false;
FTPSClient ftpClient = getFTPSClient();
if (ftpClient == null) {
logFTPConnectionError();
return false;
}
try {
loginToFTPServer(ftpClient);
result = uploadFileToFTPServer(ftpClient, inputFilePath, destinationFolderName);
} catch (Exception e) {
logErrorUploadingFile(inputFilePath, e);
return false;
} finally {
try {
logoutFromFTPServer(ftpClient);
} catch (Exception e) {
logErrorUploadingFile(inputFilePath, e);
result = false;
}
}
return result;
}
private FTPSClient getFTPSClient() {
FTPSClient ftpClient = null;
try {
ftpClient = new FTPSClient();
LOGGER.debug("Connecting to FTP server...");
ftpClient.setConnectTimeout(connectTimeOut);
ftpClient.connect(server);
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
LOGGER.error("Could not connect to FTP server. Aborting.");
return null;
}
} catch (Exception e) {
LOGGER.error("Could not connect to FTP server.", e);
return null;
}
return ftpClient;
}
private void loginToFTPServer(FTPSClient ftpClient) throws Exception {
ftpClient.setDataTimeout(DATA_TIMEOUT);
ftpClient.login(ftpUserName, ftpPassword);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
LOGGER.debug("FTP Client Buffer Size Before:" + ftpClient.getBufferSize());
ftpClient.setBufferSize(BUFFER_SIZE);
LOGGER.debug("FTP Client Buffer Size After:" + ftpClient.getBufferSize());
ftpClient.execPBSZ(0);
ftpClient.execPROT("P");
ftpClient.setControlKeepAliveTimeout(300);
LOGGER.debug("Logged into FTP server.");
}
private void logoutFromFTPServer(FTPSClient ftpClient) throws Exception {
LOGGER.debug("Logging out from FTP server.");
ftpClient.logout();
ftpClient.disconnect();
LOGGER.debug("FTP server connection closed.");
}
private boolean uploadFileToFTPServer(FTPSClient ftpClient, String inputFilePath, String destinationFolderName) {
boolean result = false;
String remoteLocationFile;
File ftpFile = new File(inputFilePath);
try (InputStream inputStream = new FileInputStream(ftpFile)) {
String fileName = ftpFile.getName();
remoteLocationFile = (destinationFolderName == null || destinationFolderName.isEmpty())
? ftpFile.getName()
: destinationFolderName + File.separator + fileName;
LOGGER.info("Storing file " + ftpFile.getName() + " of size "
+ ftpFile.length() + " in folder " + remoteLocationFile);
result = ftpClient.storeFile(remoteLocationFile, inputStream);
if(result) {
LOGGER.info("Successfully stored file " + ftpFile.getName() + " in folder " + remoteLocationFile);
} else {
LOGGER.error("Unable to store file " + ftpFile.getName() + " in folder " + remoteLocationFile);
}
return result;
} catch (Exception e) {
logErrorUploadingFile(inputFilePath, e);
}
return result;
}
The application is hosted in apache tomcat 8. What could be other causes of this issue and how should we fix them? This is crucial functionality of our application and we may even consider to use alternate API if that is stable. Please suggest.
Adding ftpClient.setSoTimeout(20000); has fixed the issue.
Adding a enterLocalPassiveMode right before the retreiveFile should solve this issue.
You also need to add
ftpClient.setControlKeepAliveTimeout(300);
or Check this code which will resolve the hanging issue

Implementing resource queue in rx

I have a hot observable Observable<Resource> resources that represents consumable resources and I want to queue up consumers Action1<Resource> for these resources. A Resource can be used by at most 1 consumer. It should not be used at all once a new value is pushed from resources. If my consumers were also wrapped in a hot observable then the marble-diagram of what I'm after would be
--A--B--C--D--E--
----1----2--34---
----A----C--D-E--
----1----2--3-4--
I've managed a naive implementation using a PublishSubject and zip but this only works if each resource is consumed before a new resource is published (i.e. instead of the required sequence [A1, C2, D3, E4] this implementation will actually produce [A1, B2, C3, D4]).
This is my first attempt at using rx and I've had a play around with both delay and join but can't quite seem to get what I'm after. I've also read that ideally Subjects should be avoided, but I can't see how else I would implement this.
public class ResourceQueue<Resource> {
private final PublishSubject<Action1<Resource>> consumers = PublishSubject.create();
public ResourceQueue(Observable<Resource> resources) {
resources.zipWith(this.consumers, new Func2<Resource, Action1<Resource>, Object>() {
#Override
public Object call(Resource resource, Action1<Resource> consumer) {
consumer.execute(resource);
return null;
}
}).publish().connect();
}
public void queue(final Action1<Resource> consumer) {
consumers.onNext(consumer);
}
}
Is there a way to achieve what I'm after? Is there a more 'rx-y' approach to the solution?
EDIT: changed withLatesFrom suggestion with combineLatest.
The only solution I can think of is to use combineLatest to get all the possible combinations, and manually exclude the ones that you do not need:
final ExecutorService executorService = Executors.newCachedThreadPool();
final Observable<String> resources = Observable.create(s -> {
Runnable r = new Runnable() {
#Override
public void run() {
final List<Integer> sleepTimes = Arrays.asList(200, 200, 200, 200, 200);
for (int i = 0; i < sleepTimes.size(); i++) {
try {
Thread.sleep(sleepTimes.get(i));
} catch (Exception e) {
e.printStackTrace();
}
String valueOf = String.valueOf((char) (i + 97));
System.out.println("new resource " + valueOf);
s.onNext(valueOf);
}
s.onCompleted();
}
};
executorService.submit(r);
});
final Observable<Integer> consumers = Observable.create(s -> {
Runnable r = new Runnable() {
#Override
public void run() {
final List<Integer> sleepTimes = Arrays.asList(300, 400, 200, 0);
for (int i = 0; i < sleepTimes.size(); i++) {
try {
Thread.sleep(sleepTimes.get(i));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("new consumer " + (i + 1));
s.onNext(i + 1);
}
s.onCompleted();
};
};
executorService.submit(r);
});
final LatestValues latestValues = new LatestValues();
final Observable<String> combineLatest = Observable.combineLatest(consumers, resources, (c, r) -> {
if (latestValues.alreadyProcessedAnyOf(c, r)) {
return "";
}
System.out.println("consumer " + c + " will consume resource " + r);
latestValues.updateWithValues(c, r);
return c + "_" + r;
});
combineLatest.subscribe();
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);
The class holding the latest consumers and resources.
static class LatestValues {
Integer latestConsumer = Integer.MAX_VALUE;
String latestResource = "";
public boolean alreadyProcessedAnyOf(Integer c, String r) {
return latestConsumer.equals(c) || latestResource.equals(r);
}
public void updateWithValues(Integer c, String r) {
latestConsumer = c;
latestResource = r;
}
}

Handling HTTP 302 Moved Temporarily requests in netty

I am using netty http client to fetch urls using netty. However, for some urls which are redirecting to some other page, I am unable to fetch the content of the final page using my client. I want to know how to handle 302 redirects in my response handler.
Below is the code used in messageReceived function of my response handler.
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
if (!readingChunks) {
HttpResponse response = (HttpResponse) e.getMessage();
System.out.println("STATUS: " + response.getStatus());
System.out.println("VERSION: " + response.getProtocolVersion());
System.out.println();
if (!response.getHeaderNames().isEmpty()) {
for (String name: response.getHeaderNames()) {
for (String value: response.getHeaders(name)) {
System.out.println("HEADER: " + name + " = " + value);
}
}
System.out.println();
}
if (response.isChunked()) {
readingChunks = true;
System.out.println("CHUNKED CONTENT {");
} else {
ChannelBuffer content = response.getContent();
if (content.readable()) {
System.out.println("CONTENT {");
System.out.println(content.toString(CharsetUtil.UTF_8));
System.out.println("} END OF CONTENT");
}
}
} else {
HttpChunk chunk = (HttpChunk) e.getMessage();
if (chunk.isLast()) {
readingChunks = false;
System.out.println("} END OF CHUNKED CONTENT");
} else {
System.out.print(chunk.getContent().toString(CharsetUtil.UTF_8));
System.out.flush();
}
}
}