Summing the values of multiple Vectors in the session - gatling

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

Related

How to buffer and drop a chunked bytestring with a delimiter?

Lets say you have a publisher using broadcast with some fast and some slow subscribers and would like to be able to drop sets of messages for the slow subscriber without having to keep them in memory. The data consists of chunked ByteStrings, so dropping a single ByteString is not an option.
Each set of ByteStrings is followed by a terminator ByteString("\n"), so I would need to drop a set of ByteStrings ending with that.
Is that something you can do with a custom graph stage? Can it be done without aggregating and keeping the whole set in memory?
Avoid Custom Stages
Whenever possible try to avoid custom stages, they are very tricky to get correct as well as being pretty verbose. Usually some combination of the standard akka-stream stages and plain-old-functions will do the trick.
Group Dropping
Presumably you have some criteria that you will use to decide which group of messages will be dropped:
type ShouldDropTester : () => Boolean
For demonstration purposes I will use a simple switch that drops every other group:
val dropEveryOther : ShouldDropTester =
Iterator.from(1)
.map(_ % 2 == 0)
.next
We will also need a function that will take in a ShouldDropTester and use it to determine whether an individual ByteString should be dropped:
val endOfFile = ByteString("\n")
val dropGroupPredicate : ShouldDropTester => ByteString => Boolean =
(shouldDropTester) => {
var dropGroup = shouldDropTester()
(byteString) =>
if(byteString equals endOfFile) {
val returnValue = dropGroup
dropGroup = shouldDropTester()
returnValue
}
else {
dropGroup
}
}
Combining the above two functions will drop every other group of ByteStrings. This functionality can then be converted into a Flow:
val filterPredicateFunction : ByteString => Boolean =
dropGroupPredicate(dropEveryOther)
val dropGroups : Flow[ByteString, ByteString, _] =
Flow[ByteString] filter filterPredicateFunction
As required: the group of messages do not need to be buffered, the predicate will work on individual ByteStrings and therefore consumes a constant amount of memory regardless of file size.

Elasticsearch groovy script to check parameter inclusion in array

I'm using elasticsearch (v2.0.0) for search in Rails and want to add to our custom script for scoring, but I'm either messing up the syntax or just missing something else entirely. It all works without the check in the script for the array, so that's the only part that's not working.
So for the index, recipe_user_ids is an array of integers:
indexes :recipe_user_ids, type: 'integer'
Then in the search query I specify the parameter for the script file and which script file:
functions: [{
script_score: {
params: { current_user_id: user.id },
script_file: 'ownership_script'
}
}]
And the ownership-script.groovy file:
if (current_user_id == doc['user_id'].value) { owner_modifier = 1.0 } else { owner_modifier = 0.0 }
if (doc['recipe_user_ids'].values.contains(current_user_id)) { recipe_user_modifier = 50.0 } else { recipe_user_modifier = 0.0 }
(_score + (doc['score_for_sort'].value + owner_modifier + recipe_user_modifier)*5)/_score
I'm not getting any errors, but the results don't seem to match what I'd expect when the recipe_user_ids array does contain current_user_id, so everything is falling into the else statement. Is it a type issue, syntax? Any tips greatly appreciated.
This seems to occur due to mismatch in type caused by autoboxing.
The doc['field_name].values for field mapping short, integer, long types seems to be returning a collection always of type 'Long' and the argument to contains is autoboxed to Integercausing contains to fail.
You could probably explictly cast current_user_id to the type of Long:
Example:
doc['recipe_user_ids'].values.contains(new Long(current_user_id))
Or better to use the 'find' method
doc['recipe_user_ids'].values.find {it == current_user_id}

Comparing array with array of hashes and outputing new array of hashes

I have an array of subscription instances #subscription_valids and an array of subscribed player that look like that :
array_subscribed_players = [{"name0" => "link1"}, {"name1"=>"link2"}, {"name2"=>"link3"}....]
What I need to do is : for each subscription in #subscription_valids :
#subscription_valids.each do |subscription|
I need to check if subscription.user.full_name or if subscription.user.full_name_inversed matches a key in one of the hashes of array_subscribed_player (in the exemple "name0", "name1" or "name2").
If it matches then I should store the relevant subscription as key in a hash in a new array and extract the relevant link as value of this hash. My final outpout should be an array that looks like this :
[{subscription1 => "link1"}, {subscription2 => "link2}, ...]
else if the subscription.user.full_name doesnt match i'll just store the subscription in a failure array.
How can I achieve this result ?
See http://ruby-doc.org/core-2.2.3/Hash.html
A user-defined class may be used as a hash key if the hash and eql?
methods are overridden to provide meaningful behavior. By default,
separate instances refer to separate hash keys.
so I think you should override your .eql? method in #subscription_valids to something meaningful (like a unique string)
I can't think for a Array method so you can go like:
demo
results = []
failures = []
#subscription_valids.each do |subscription|
array_subscribed_players.each do |player|
if player.keys.first == subscription.user.full_name || player.keys.first == subscription.user.full_name_inversed
results << { subscription => player[player.keys.first] }
else
failures << subscription
end
end
end
You can try the following:
valid = array_subscribed_players.select{|x| #subscription_valids.map(&:name).include?(x.keys.first)}
Demo
If you need to store both valid and invalid values somewhere:
valid, invalid = array_subscribed_players.partition{|x| #subscription_valids.map(&:name).include?(x.keys.first)}

Protractor returning a value from a promise

I'm writing a test to see if my code is removing a level by looking at a text value on the screen which holds the count of levels.
it 'allows deleting level versions', ->
browser.get('/api#/costings')
element(By.id("edit")).click()
startCount = element(By.id("versions_count")).getText().then( (count) ->
return count
)
element(By.id("versions")).click()
first=element.all(By.id("listing")).first()
first.element(By.id("delete")).click()
helper.accept_dialog()
element(By.id("back")).click()
expect(element(By.id("versions_count")).getText()).toEqual(startCount - 1)
Problem here is startCount results in a function. I cannot seem to get startCount into an integer so that I can see if the count has gone down by 1 item.
It gives me the error;
1) edit an existing costing allows deleting level versions
Message:
Expected '1' to equal NaN.
If I try parseInt(startCount) I get the same error.
The variable startCount is a promise, and so startCount - 1 doesn't make sense: there is no automatic type conversion from a promise to its resolved value, so you can't subtract one from it.
What you can do, is create a promise whose resolved value is the expected versions count:
expectedCount = element(By.id("versions_count")).getText().then( (count) ->
return (count - 1).toString();
)
and then you can pass this promise to toEqual, as it automatically unwraps promises at the appropriate point in the control flow
expect(element(By.id("versions_count")).getText()).toEqual(expectedCount)
it("Verify Add Element", function(){
basePage.gotoAssetsPage();
var numberOfElementsBefore = assetsPage.getTotalAssertsNumber();//get text from counter
assetsPage.createAsset(); // add one object on the page
var numberOfElementsAfter = assetsPage.getTotalAssertsNumber(); // get text from counter after creation of object
numberOfElementsBefore.then(function(startNumberText) {
console.log("Number of Asserts before test is " + startNumberText);
return startNumberText;
});
numberOfElementsAfter.then(function(endNumberText) {
console.log("Number of Asserts after test is " + endNumberText);
expect(assertsBefore).toBe((endNumberText-1).toString());
});
});
In this test I'm verifying, that quantity of elements before text will equals quantity of elements after test minus 1.
If I not use .toString(), test result will be: Expect '21' to be 21. So, converting to string works. Maybe someone have a better solution :)

Caching of Function Results

I essentially want to write a bunch of commonly used queries in a web application of this format:
SELECT *
FROM secure_table
WHERE security_function(value 1, value 2) = true;
Value 1 and value 2 will have a limited enough range of values for the idea of caching the result of the security function to be potentially very useful in improving application performance. We would also need to be able to trigger a reset of the cache at will since some conditions would render the cached values out of date.
Is there an out of the box way of doing this with SQL Server (I believe we will be using the 2012 version)? I've had a google around and seen nothing concrete, some references to ASP.NET state but nothing concrete about what that actually involves, and some references to memcached, but that wouldn't seem to go down to function level, so doesn't seem suitable either.
EDIT:
So I would like the function to work something like this:
function security_function(val1, val2) {
result = getFromCache(val1, val2)
if result is empty then
result = //do big complicated query
addToCache(val1, val2, result)
end
return result
}
If you are using ASP.Net you can use the cache object to store the results of the query:
in c#:
Results GetResults(string value1, string value2)
{
string cacheItemName = "cacheItem-" + value1 + "-" + value2;
if (Cache[cacheItemName] != null)
{
return Cache[cacheItemName];
}
else
{
var result = // do big complicated query;
Cache.Insert(cacheItemName, result,
null, DateTime.Now.AddMinutes(15d), // Expire after 15 minutes
System.Web.Caching.Cache.NoSlidingExpiration);
return result;
}
}

Resources