How to properly initialize Elasticsearch for queries? - elasticsearch

I wrote a program that inserts an element, then it searches all elements in the store. Thus, it finds one more element every time the program runs. I’d expect to be able to comment out the insert and still run the program, just finding the stuff that was already inserted. Whenever I do though, I get an exception “Failed to execute phase [query_fetch], all shards failed”. Any ideas?
Hypothesis: inserting the element does some sort of implicit initialization on my node. However, I’m looking through the ES source, and I can’t figure out what that would be.
try (Node node = NodeBuilder.nodeBuilder().clusterName("tesssst").build().start()) {
try (Client client = node.client()) {
//insert an entry; if this part is removed, the program crashes
client.prepareIndex("movies", "movie", UUID.randomUUID().toString()).setSource(
"{\"title\": \"Lawrence of Arabia\",\"director\": \"David Lean\",\"year\": 1962,\"genres\":"
+ " [\"Adventure\", \"Biography\", \"Drama\"]}").execute().actionGet();
//search all entries
System.out.println("***************");
SearchResponse response = client.prepareSearch("movies")
.setTypes("movie")
.setSearchType(SearchType.QUERY_AND_FETCH)
.setFrom(0).setSize(60).setExplain(true)
.execute()
.actionGet();
SearchHit[] results = response.getHits().getHits();
System.out.println("Current results: " + results.length);
for (SearchHit hit : results) {
System.out.println("------------------------------");
Map<String, Object> result = hit.getSource();
System.out.println(result);
}
System.out.println("***************");
client.close();
}
node.close();
}

The problem was that Elasticsearch didn't have enough time to startup, but the initial insert gave it enough time. Simply adding an appropriate wait fixes it:
final ClusterHealthRequest clusterHealthRequest = new ClusterHealthRequest("movies")
.timeout(TimeValue.timeValueSeconds(60)).waitForGreenStatus();
final ClusterHealthResponse clusterHealth = client.admin().cluster()
.health(clusterHealthRequest).actionGet();
if (clusterHealth.isTimedOut()) {
System.out.println("ElasticSearch cluster health timed out");
} else {
System.out.println("ElasticSearch cluster health: Status "
+ clusterHealth.getStatus().name() + "; " + clusterHealth.getNumberOfNodes()
+ " nodes; " + clusterHealth.getActiveShards() + " active shards.");
}
(if your standards are lower, you can save time with waitForYellowStatus)

Related

How do I get the get list of connections from processContext in NiFi 1.11.4

Our production instance of NiFi is version 1.8.0. We have a custom processor that continually looks at it's downstream connections in order to route flow files based on the connection's queue size.
Here is the salient snippet of how we do this . . .
String processorId = this.getIdentifier();
ProcessorGroupStatus processGroupStatus = ((EventAccess) getControllerService()).getContollerStatus();
Collection<ConnectionStatus> groupConnections = processGroupStatus.getConnectionStatus();
ArrayList connections = new ArrayList<>(groupConnections);
for (Object processorConnection : connections) {
ConnectionStatus connection = (ConnectionStatus) processorConnection;
if(connection.getSourceId().equals(processorId){
//do stuff with connection.getQueuedCount() & connection.getQueuedBytes()
break;
}
}
Everything has been working as expected for the last couple of years. However, upgrading our NiFi instance to version 1.11.4 has broken this approach. The exception thrown is:
class org.apache.nifi.contoller.serviceStandardContollerServiceProvider cannot be cast to class org.apache.nifi.reporting.EventAccess
Is there another way to retrieve connections from processContext?
One approach that may be more upwardly compatible (and easier to maintain) than a custom Java processor would be to use the ExecuteGroovyScript processor.
The Groovy script in this case would look something like:
ff = session.get()
if (ff) {
me = context.procNode
processorId = me.identifier
connections = me.processGroup.connections
connections.each { connection ->
if(connection.source.identifier.equals(processorId)) {
ff[connection.identifier] = "I am the source " +
"[" + connection.flowFileQueue.size().objectCount + "]" +
"[" + connection.flowFileQueue.size().byteCount + "]"
}
else {
ff[connection.identifier] = "I am NOT the source; my name is [" + connection.name + "]"
}
}
REL_SUCCESS << ff
}
To find out what is available to the Groovy script, I use a combination of the NiFi JavaDocs (https://javadoc.io/static/org.apache.nifi/nifi-api/1.12.0/index.html) and the Github code for NiFi (https://github.com/apache/nifi/tree/c396927299586b896df4ebc745793b4c451f3898/nifi-api/src/main/java/org/apache/nifi).
As a side note, we converted our custom Java processors to Groovy script, because of an upgrade incompatibility when going to (ironically) 1.8.0. We have not had an issue with NiFi upgrades since then, and are currently running v 1.11.4.

Flowfiles stuck in queue (Apache NiFi)

I have following flow:
ListFTP -> RouteOnAttribute -> FetchFTP -> UnpackContent -> ExecuteScript.
Some of files are stuck in queue UnpackContent -> ExecuteScript.
ExecuteScript ate some flowfiles and they just disappeared: failure and success relationships are empty. It just showed some activity in Tasks/Time field. All of them stuck in queue before ExecuteScript. I tried to empty queue, but not all of flowfiles have been deleted from this queue. About 1/3 of them still stuck in queue. I tried to disable all processors and empty queue again but it returns: 0 FlowFiles (0 bytes) were removed from the queue.
When i'm trying to change Connection destionation it returns:
Cannot change destination of Connection because FlowFiles from this Connection are currently held by ExecuteScript[id=d33c9b73-0177-1000-5151-83b7b938de39]
ExecuScript from this answer (uses Python).
So, I can't empty queue because its always return message that there is no any flowfile, and i can't remove connection. This has been going on for several hours.
Connection configuration:
Scheduling is set to 0 sec, no penalties for flowfiles, etc.
Is it script problem?
UPDATE
Changed script to:
flowFile = session.get()
if (flowFile != None):
# All processing code starts at this indent
if errorOccurred:
session.transfer(flowFile, REL_FAILURE)
else:
session.transfer(flowFile, REL_SUCCESS)
# implicit return at the end
Same result.
UPDATE v2
I set concurent tasks to 50 and then ran ExecuteScript again and terminated it. I got this error:
UPDATE v3
I created additional ExecuteScript processor with same script and it works fine. But after i stopped this new processor and create new flowfiles, this processor now have same problems: it's just stuck.
Hilarious. Is ExecuteScript for single use?
You need to modify Your code in nifi-1.13.2 because NIFI-8080 caused these bugs. Or you just use nifi 1.12.1
JythonScriptEngineConfigurator:
#Override
public Object init(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException {
// Always compile when first run
if (engine != null) {
// Add prefix for import sys and all jython modules
prefix = "import sys\n"
+ Arrays.stream(modulePaths).map((modulePath) -> "sys.path.append(" + PyString.encode_UnicodeEscape(modulePath, true) + ")")
.collect(Collectors.joining("\n"));
}
return null;
}
#Override
public Object eval(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException {
Object returnValue = null;
if (engine != null) {
returnValue = ((Compilable) engine).compile(prefix + scriptBody).eval();
}
return returnValue;
}

Parse Cloud "beforeSave" not saving data

I'm using parse beforeSave method to save an order, here is the code:
//Before save an order - if finish - set priority to 0
Parse.Cloud.beforeSave("UserToOrders", function(request, response) {
Parse.Cloud.useMasterKey();
var preStatus = request.object.get("OrderStatus");
if (preStatus == "Finish") {
request.object.set("Priority",0);
console.log("beforeSave(\"UserToOrders\")\t Order (" + request.object.id + ") Status is 'Finish' So Priority set to '0'");
}
else {
console.log("beforeSave(\"UserToOrders\")\t Order (" + request.object.id + ") Status Changed to: " + preStatus);
request.object.set("OrderStatus",preStatus);
}
response.success();
});
Here is the log:
I2016-03-09T20:56:05.779Z]v136 before_save triggered for UserToOrders for user pSi0iCGJJe:
Input: {"original":{"ACL":{"*":{"read":true},"vxgEWFQ7eu":{"read":true,"write":true}},"OrderStatus":"Ready","OrderStatusActivity":"Active","ResturantID":"g1bzMQEXoj","TimeToBeReady":{"__type":"Date","iso":"2016-03-08T23:35:23.916Z"},"UserETA":{"__type":"Date","iso":"2016-03-08T23:35:23.916Z"},"UserID":"vxgEWFQ7eu","createdAt":"2016-03-08T21:06:06.605Z","objectId":"t3NoxcSp5z","updatedAt":"2016-03-08T21:40:59.538Z"},"update":{"OrderStatus":"Finish","objectId":"t3NoxcSp5z"}}
Result: Update changed to {"OrderStatus":"Finish","Priority":0}
I2016-03-09T20:56:05.975Z]beforeSave("UserToOrders") Order (t3NoxcSp5z) Status is 'Finish' So Priority set to '0'
but nothing is being changed in the DB.
What do i miss?
Thanks.
in var preStatus is the same value as you wanted to save...
var preStatus = request.object.get("OrderStatus");
and you are "saving" the same value, you can just delete this line
request.object.set("OrderStatus",preStatus);
if it is not what you want, provide the log from "OrderStatus" = Finish
I've figured it out. It was an ACL permissions issue.
The Order created by one client, while the chance made by another one.

How to speed up a simple count operation in SORM?

I'm trying to perform a simple count operation on a large table with SORM. This works inexplicably slow. Code:
case class Tests (datetime: DateTime, value:Double, second:Double)
object DB extends Instance (
entities = Set() +
Entity[Tests](),
url = "jdbc:h2:~/test",
user = "sa",
password = "",
poolSize = 10
)
object TestSORM {
def main(args: Array[String]) {
println("Start at " + DB.now())
println(" DB.query[Tests].count() = " + DB.query[Tests].count())
println("Finish at " + DB.now())
DB.close()
}
}
Results:
Start at 2013-01-28T22:36:05.281+04:00
DB.query[Tests].count() = 3390132
Finish at = 2013-01-28T22:38:39.655+04:00
It took two and a half minutes!
In H2 console 'select count(*) from tests' works in a tick. What is my mistake? Can I execute a sql query through it?
Thanks in advance!
It's a known optimization issue. Currently SORM does not utilize a COUNT operation. Since finally the issue has come up, I'll address it right away. Expect a release fixing this in the comming days.
The issue fix has been delayed. You can monitor its status on the issue tracker.

Azure Storage Queue very slow from a worker role in the cloud, but not from my machine

I'm doing a very simple test with queues pointing to the real Azure Storage and, I don't know why, executing the test from my computer is quite faster than deploy the worker role into azure and execute it there. I'm not using Dev Storage when I test locally, my .cscfg is has the connection string to the real storage.
The storage account and the roles are in the same affinity group.
The test is a web role and a worker role. The page tells to the worker what test to do, the the worker do it and returns the time consumed. This specific test meassures how long takes get 1000 messages from an Azure Queue using batches of 32 messages. First, I test running debug with VS, after I deploy the app to Azure and run it from there.
The results are:
From my computer: 34805.6495 ms.
From Azure role: 7956828.2851 ms.
That could mean that is faster to access queues from outside Azure than inside, and that doesn't make sense.
I'm testing like this:
private TestResult InQueueScopeDo(String test, Guid id, Int64 itemCount)
{
CloudStorageAccount account = CloudStorageAccount.Parse(_connectionString);
CloudQueueClient client = account.CreateCloudQueueClient();
CloudQueue queue = client.GetQueueReference(Guid.NewGuid().ToString());
try
{
queue.Create();
PreTestExecute(itemCount, queue);
List<Int64> times = new List<Int64>();
Stopwatch sw = new Stopwatch();
for (Int64 i = 0; i < itemCount; i++)
{
sw.Start();
Boolean valid = ItemTest(i, itemCount, queue);
sw.Stop();
if (valid)
times.Add(sw.ElapsedTicks);
sw.Reset();
}
return new TestResult(id, test + " with " + itemCount.ToString() + " elements", TimeSpan.FromTicks(times.Min()).TotalMilliseconds,
TimeSpan.FromTicks(times.Max()).TotalMilliseconds,
TimeSpan.FromTicks((Int64)Math.Round(times.Average())).TotalMilliseconds);
}
finally
{
queue.Delete();
}
return null;
}
The PreTestExecute puts the 1000 items on the queue with 2048 bytes each.
And this is what happens in the ItemTest method for this test:
Boolean done = false;
public override bool ItemTest(long itemCurrent, long itemCount, CloudQueue queue)
{
if (done)
return false;
CloudQueueMessage[] messages = null;
while ((messages = queue.GetMessages((Int32)itemCount).ToArray()).Any())
{
foreach (var m in messages)
queue.DeleteMessage(m);
}
done = true;
return true;
}
I don't what I'm doing wrong, same code, same connection string and I got these resuts.
Any idea?
UPDATE:
The problem seems to be in the way I calculate it.
I have replaced the times.Add(sw.ElapsedTicks); for times.Add(sw.ElapsedMilliseconds); and this block:
return new TestResult(id, test + " with " + itemCount.ToString() + " elements",
TimeSpan.FromTicks(times.Min()).TotalMilliseconds,
TimeSpan.FromTicks(times.Max()).TotalMilliseconds,
TimeSpan.FromTicks((Int64)Math.Round(times.Average())).TotalMilliseconds);
for this one:
return new TestResult(id, test + " with " + itemCount.ToString() + " elements",
times.Min(),times.Max(),times.Average());
And now the results are similar, so apparently there is a difference in how the precision is handled or something. I will research this later on.
The problem apparently was a issue with different nature of the StopWatch and TimeSpan ticks, as discussed here.
Stopwatch.ElapsedTicks Property
Stopwatch ticks are different from DateTime.Ticks. Each tick in the DateTime.Ticks value represents one 100-nanosecond interval. Each tick in the ElapsedTicks value represents the time interval equal to 1 second divided by the Frequency.
How is your CPU utilization? Is this possible that your code is spiking the CPU and your workstation is much faster than your Azure node?

Resources