Dealing with recursion/sync-loops in coffeescript - coffeescript

Right now I'm trying to build some code to handle lists over 100 items, as returned by the Amazon API endpoints. This requires building page-support into our data-gathering routines. This is my first time doing much with coffeescript, so I'm running into some conceptual walls here.
In a less async language, what I'm trying to do would be handleable using an until loop:
puts "Fetching launch configs"
next_token = ''
do
if next_token.length > 0
page_list = get_autoscale_configs(next_token)
else
page_list = get_autoscale_configs
if page_list.NextToken is undefined
next_token = ''
else
next_token = page_list.NextToken
until(next_token.length == 0)
The method of doing this in coffeescript is eluding me. What I have now...
populate_configs = ( ) ->
process_results = ( err data ) ->
if err
return err
# do some logic
if data.NextToken
saved.next_token = data.NextToken
else
saved.next_token = ''
return console.log "Finished parsing #{data.LaunchConfigurations.length} items."
if saved.next_token = ''
autoscaling.describeLaunchConfigurations {
MaxRecords: 100, StartToken: next_token
}, ( err, data ) -> process_results( err, data )
else
autoscaling.describeLaunchConfigurations {
MaxRecords: 100
}, ( err, data ) -> process_results( err, data )
And then in the body of the code, this function is invoked:
saved = {}
async.series [
( series_cb ) ->
saved.next_token = ''
async.doWhilst populate_configs,
saved.next_token.length > 4,
( err ) ->
if err
# complain about it.
# else, log success
return series_cb()
# more callbacks
]
The idea here being that populate_configs is called by doWhilst, which then fetches a list of launch_configs out of amazon. The data is then passed into another function called process_results, which persists things that should be persisted and sets variables for next_token. It returns, and doWhilst tests to see if the test is passing (the string-length of saved.next_token is long enough to be data); if it passes, it runs through populate_configs again, if it fails, it runs the third callback.
What I'm getting right now is that the first iteration of that populate_configs block is executed, but then the entire execution stops dead at that point. None of the calls in the error-handler of doWhilst are being executed.
Clearly, I'm misunderstanding how callbacks work and how to get myself out of this hole. This part needs to be synchronous. Once I have this list built, I can do all sorts of async fun with the list I'm building. But I need the list first.

I think the issue is here: if saved.next_token = ''. You set next_token to '' so populate_configs runs only once. The comparaison is done with == or is in CoffeeScript.
Also, ( err, data ) -> process_results( err, data ) can be replaced by process_results.

Related

How to pass dynamic variable in object while parsing json

I have been trying to parse a object ,using Foreach ,
it works good when i use :
this.parsedUserInfo.info.tw // or discord any.. from the below list.
I want to make the code small using foreach loop but the dyanmic value 'social' is not getting added to the parse statement in if else loop.
My code below:
this.parsedUserInfo = UserInfo.fromJson(jsonDecode(value.data)),
['tw', 'discord', 'telegram', 'fb', 'tumblr'].forEach((social) {
if (('this.parsedUserInfo.info.' + social != '')) { //if loop is not working properly.
this
.parsedPlatforms
.data[this
.parsedPlatforms
.data
.indexWhere((row) => row.socid == social)]
.connected = true;
}

JPA: the better way of getting the first object in a list of ordered objects?

I need to retrieve the most recently updated object. Currently I am able to retrieve it by first doing something similar to the following:
em.createQuery("select m from MyObject m order by m.updateTime").setFirstResult(0).setMaxResults(1).getResultList()
and then getting the only object if the result list is not empty. I am curious whether there is any better way of doing this type of thing.
Thanks and regards.
Setting first result to 0 is redundant in this case and if you need just one row then you could use a getSingleResult() function.
So your code could be modified as follows:
MyObject myObject = em.createQuery("select m from MyObject m order by m.updateTime").setMaxResults(1).getSingleResult();
EDIT: as Tiny has mentioned in the comment in case when there are no matching rows the code will throw a NoResultException which is to be handled (e.g. assign a null value in this case).
EDIT2:
I've checked the Hibernate implementation of both methods and it turned out that getSingleResult() has all the code that getResultList() has and on top of that the following block:
if ( result.size() == 0 ) {
NoResultException nre = new NoResultException( "No entity found for query" );
getEntityManager().handlePersistenceException( nre );
throw nre;
}
else if ( result.size() > 1 ) {
final Set<X> uniqueResult = new HashSet<X>(result);
if ( uniqueResult.size() > 1 ) {
NonUniqueResultException nure = new NonUniqueResultException( "result returns more than one elements" );
getEntityManager().handlePersistenceException( nure );
throw nure;
}
else {
return uniqueResult.iterator().next();
}
}
else {
return result.get( 0 );
}
thus you end up with a slower implementation when using getSingleResult().
EDIT3: getSingleResult() would be beneficial in case if having zero or more than one resulting row is an invalid/exceptional data state (i.e. if such a case occurs then you know that your data is corrupted). Since both NoResultException and NonUniqueResultException are uncatched exceptions you will end up with only one line of code (no if, no catch needed in this case).

Idiomatic way to check for parameter initialization

I have a variable param which has to be initialized at runtime.
Then, I have a part of the code which implements the following:
if (param has been initialized)
...do something...
else
print error and exit
What is the most idiomatic way to do this in Scala?
So far I have used Option[X] in this way:
var param : Option[TheType] = None
...
val param_value : TheType = x getOrElse {println("Error"); null}
But, since I have to return null it seems dirty.
How should I do it?
Simply map or foreach over it:
param.foreach { param_value =>
// Do everything you need to do with `param_value` here
} getOrElse sys.exit(3) # Param was empty, kill the program
You can also use the for comprehension style:
for {
param_value <- param
} yield yourOperation(param_value)
The upside of this is that if your calling code is expecting to do something with param_value as a return value from yourMethod you will encode the possibility of param_value not existing in your return type (it will be an Option[TheType] rather than a potentially null TheType.)
I might me wrong but it seems to me that the use of Future would fit with your problem: Instead of explicitly checking whether your required param_value has been initialized and finish the program if not, you could make your resource dependent code to execute when the resource has been rightly initialized:
val param: Future[TheType] = future {
INITIALIZATION CODE HERE
}
param onFailure {
case e => println("Error!");
}
param onSuccess {
case param_value: TheType => {
YOUR BUSINESS CODE HERE
}
}

Scala Future onComplete callback not executing immediately

I have a Future[Future[Set[String]]. I flatmap it to return a Future[Set[String]]. I wait for infinity (I know this is bad) and then check if the Future is complete. It returns true. However, when I get the value returned by Future and try to add it to a Set, it doesn't add it. Statements at the end of the callback get printed first. When I return the Set from the method, it is always empty though the Future does return values. I have added comments as to explain the sequence of events happening. Please point me if I am doing something wrong! Thanks!
val googleXfpSegments = Set[String]()
val customCriteriaFuture: Future[List[Long]] = getCustomCriteriaValueIds(lineItemPage.getResults())
// getCustomCriteriaValues returns a Future[Set[String]]
val criteriaValueList = customCriteriaFuture.flatMap(criteriaIdList => getCustomCriteriaValues(criteriaIdList.toSet))
// I wait for infinite time
Await.result(criteriaValueList, scala.concurrent.duration.Duration.Inf)
log.info("Future Completed = " + criteriaValueList.isCompleted) // This returns true
criteriaValueList onComplete {
case Success(segmentNames) => {
// This statement gets printed after the "TEST" value gets printed
log.info("SegmentNameList = " + segmentNames.mkString(","))
googleXfpSegments ++= segmentNames
// This prints nothing which means the segmentNames is not getting added
log.info("Google Segments = " + googleXfpSegments.mkString(","))
}
case Failure(error) => log.error("Error occurred ", error)
}
googleXfpSegments += "TEST"
// This prints TEST
log.info("Google Segments = " + googleXfpSegments.mkString(","))
Log output is shown below:
[info] [INFO] [2014-12-09 17:25:01,147] [service.GoogleXFPService] Future Completed = true
[info] [INFO] [2014-12-09 17:25:01,148] [service.GoogleXFPService] Google Segments = TEST
[info] [INFO] [2014-12-09 17:25:01,148] [service.GoogleXFPService] SegmentNameList = vt.cm,vt.cp,ex.qy,ex.ahe,cm.gannett_trav
You need to assign the output of Await.result(criteriaValueList, scala.concurrent.duration.Duration.Inf) to a value. Currently you are waiting for it to complete, doing nothing with the output, then attaching an onComplete callback to an already completed future, then your program terminates before the callback can run.
val segmentNames = Await.result(criteriaValueList, scala.concurrent.duration.Duration.Inf)
log.info("Google Segments = " + segmentNames.mkString(","))

Higher order functions not working in casperjs

I have function defined like this
casper.executeRemote = (fn,params)->
->
try
fn.apply(this,params)
catch e
console.log(e)
getLinks = ->
elems = document.querySelectorAll('#pagination-flickr a')
and i am calling the function like below
casper.then ->
all_links = #evaluate #executeRemote getLinks
casper.log all_links,'debug'
However I get the below error when i try to run this in casperjs
ReferenceError: Can't find variable: fn
The same code works fine, if i try in a browser console(compiled js). What is that I am doing wrong?
Of course they work, but not at the border to the page context:
Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.
Closures, functions, DOM nodes, etc. will not work!
Thankfully there is the toString function on Functions. So, you can change your code a little to account for passing the function as a string and evaling inside of the page context.
(Untested) example:
casper.executeRemote = (fn,params)->
fn = eval('('+fn+')')
try
fn.apply(this,params)
catch e
console.log(e)
getLinks = ->
elems = document.querySelectorAll('#pagination-flickr a')
casper.then ->
all_links = #evaluate(#executeRemote, getLinks.toString())
casper.log all_links,'debug'
Based on #Artjom's answer. I modified the code as shown below, then it works
executeRemote = (fn,params)->
->
try
fn.apply(this,params)
catch e
console.log(e)
getLinks = ->
elems = document.querySelectorAll('#pagination-flickr a')
links = (link.href for link in elems)
remoteWrapper = (excRm,gL)->
excRm=eval('('+excRm+')')
gL=eval('('+gL+')')
fn=excRm(gL)
fn()
casper.on 'remote.message',(message)->
#echo message
casper.then ->
all_links = #evaluate remoteWrapper, executeRemote.toString(), getLinks.toString()
casper.log all_links,'debug'