Combine spawned process outputs - coffeescript

While the following code works great to call a python script and get the output:
s = spawn 'python', ['-u', 'foo.py']
s.stdout.on 'data', (data) -> msg.send data.toString()
s.stderr.on 'data', (data) -> msg.send data.toString()
foo.py returns many different responses (it returns updates as it runs).
For instance:
def function1():
print "Function 1 complete"
def function2():
print "Function 2 complete"
function1()
function2()
Hubot does not display those results in a consistent order. I know this can happen if msg.sendis called multiple times.
While I know I could re-write foo.py to behave differently, other processes depend on foo.py and I can't alter its behavior.
I was wondering what the process might be to collect the responses as they come and send a single msg.send in hopes that a single call to msg.send will preserve the order of the process outputs.

Imho, best would be to use promises, by the addition of q or bluebird
https://documentup.com/kriskowal/q/
http://bluebirdjs.com/docs/getting-started.html
It would lead, for example, to:
Promise.all([function1(), function2()]).then (res) ->
msg.send res.join(", ")

Related

Detect and prevent processing of sequential duplicate Tradingview webhook json

I am not very well acquainted with python, but have by much trial and error, and building upon the work of others, developed a simple working and reliable interface between Tradingview (TV) and Interactive Brokers (IB).
I have situation where occasional apparent repainting of TV charts results in duplicate orders being submitted. (Yes, I have researched methods whereby such repainting can be reduced or eliminated, but the effect of these methods greatly reduces the proven profitability of my trading algo.) I am attempting to modify my code to detect and prevent processing of duplicate orders received in sequence, as I never intend to have more than one order working for any given security and any given time. My modification attempt (see below) is quite rudimentary--simply detect whether the just-received webhook json is essentially the same as that received just previously, and ignore if so.
This is where, if you wish, you can throw stones and tell me to go read about 'ver' and 'let' and 'global'. I've tried--for hours, and just don't "get it". I'm in my 70s and come from the era of Fortran, Cobol, and Basic, when variables were simply declared (if necessary), initialized, and used. Could someone kindly help me simply to get some starting values into the two variables, xticker and xorder, in the code below? Or better yet, show me a better way to accomplish my objective?
Many thanks for any help offered!
[Edit] - Repainting noted above may possibly have resulted from my setting "calc_on_order_fills=true" and/or "process_orders_on_close="true" while also setting "calc_on_every_tick=true". I have changed the first two of these settings to "false", but have no way to ascertain if doing so gets rid of the TV alert/webhook duplicates. But irrespective of whether these script modifications are beneficial, I would still like to add a "detect and ignore duplicates" feature to my TV to IB bridge as described.
#Create root
#app.route('/', methods=['GET','POST'])
async def root(request):
return response.text('online')
#Listen for signals and execute orders
#app.route('/webhook', methods=['GET','POST'])
async def webhook(request):
if request.method == 'POST':
await checkIfReconnect()
#Parse alert data
alert = request.json
order = MarketOrder(alert['order_action'],alert['order_contracts'],account='aannnnnnn')
ticker = alert['ticker']
# Attempt to detect and prevent processing of duplicate webhook json
# Fails since xticker and xorder are undefined and have no value.
# Need to initialize xticker='dummy' and xorder='dummy' at start
# Where/how to place these two initializing statements?
if not ticker == xticker and xorder == order:
#Do stuff (process and submit valid order)
#then ...
xticker = ticker
xorder = order
return HTTPResponse("ok", 200)
return HTTPResponse("", 405)
I have tried setting xticker and xorder directly using =, var, and let, and have tried but failed to understand how local and global variable assignment works within Python. My next effort, if no assistance is offered, will be to make use of read & write operations to an external file in order to draw in initial values and then to keep track of the last valid json data-- Crude but perhaps workable-- and there must be a great many simpler and better methods, all of which are beyond my ken.
Solved my own problem using global variables after finding some examples online. Solution works as intended, with sequential duplicate orders being ignored. Relevant code extract follows:
#Create root
#app.route('/', methods=['GET','POST'])
async def root(request):
return response.text('online')
#Listen for signals and execute orders
#app.route('/webhook', methods=['GET','POST'])
async def webhook(request):
if request.method == 'POST':
await checkIfReconnect()
#Parse alert data
alert = request.json
order = MarketOrder(alert['order_action'],alert['order_contracts'],account='aannnnnnn')
ticker = alert['ticker']
action = alert['order_action']
source = alert['source']
if not (ticker == xticker and xaction == action and xsource == source):
def inner():
global xticker
xticker = ticker
global xaction
xaction = action
global xsource
xsource = source
inner()
#Do stuff (prepare and submit order to broker)
return HTTPResponse("ok", 200)
return HTTPResponse("", 405)
#Reconnect if needed
async def checkIfReconnect():
if not app.ib.isConnected() or not app.ib.client.isConnected():
app.ib.disconnect()
app.ib = IB()
app.ib.connect('127.0.0.1',7497,clientId=int(int((time.time()*1000)-1667740000000)/1000000))
#Run app
if __name__ == '__main__':
#Connect to IB
app.ib = IB()
xticker = "ticker"
xaction = "action"
xsource = "source"
app.ib.connectAsync('127.0.0.1',7497,clientId=int(int((time.time()*1000)-1667740000000)/1000000))
app.run(port=5000)

Function runs twice in console (python3, eclipse)

Hi! Could you please explain why the function runs twice in console?
def changeList(myList1):
myList2 = myList1.append(4)
print(myList2)
return
myList1 = [1,2,3]
changeList(myList1)
print (myList1)
The result in console:
None
[1, 2, 3, 4]
Does it mean function runs twice as "None" appears in the console?
tl;dr - the function is only running once -- there are two print statements producing output
The function is not running twice: indeed, it is only being run once. The output in the console is instead coming from the two calls to print() contained within your program: one inside the function changeList() and one outside the function (print(myList1)).
None is being printed to the console because the return statement within the function changeList() isn't returning anything - there is no value to return:
If an expression list is present, it is evaluated, else None is
substituted.
[Taken from the Python 3.6 Documentation]
Seeing as how the return statement isn't doing anything, you can safely remove it - the function will still end anyway.
Hope that helps you out!
The function is running only once. You are appending one item to list and tried to store in other list by just assigning list with one more item appending which returns None and assigns to myList2. So, the code is wrong because append() function return's None.
I think you wan't to do like this so, here is the correct code:
comment if is it solved your problem or not.
def changeList(myList1):
myList2=[]
myList2.extend(myList1)
myList2.append(4)
print(myList2)
return
myList1 = [1,2,3]
changeList(myList1)
print (myList1)
Because in the function definition of changeList, there is a print statement, and then another print statement after calling changeList. The function is only running once actually, but you simply have two separate print statements.

Is it possible to render a component during eval in halogen?

In my halogen project have this eval branch:
eval (SetTest tName next) = do
H.set (State Nothing)
detail <- H.fromAff $ toAff settings $ getTestsByTestname (tName ^. unTestName)
H.set (State (Just detail))
pure next
The toAff bit if off doing AJAX and may take a while to return. In my render function I have
, case ts of
Nothing ->
HH.div [class_ BS.centerBlock]
[HH.i [classes (HH.className <$> ["fa", "fa-spinner", "fa-spin", "loading"])]
[]
]
Just td ->
HH.h3_ [HH.text $ td ^. tdName<<<unTestName]
I'm naively expecting to see a loading spinner when until my aff action returns, but it looks like the eval runs all the way through before the html is rendered. Is this correct?
edit
Turns out this was user error - I was calling my Query in wrong order. Future mes: setting the state does indeed update the ui :-)
No, modifying the state during eval should indeed trigger a render. Unless your Aff isn't really async, I'm not sure why you wouldn't be seeing what you expect here.
Have you tried doing something like H.fromAff $ later' 5000 $ pure <some value>? Where later' comes from Control.Monad.Aff and <some value> is something suitable for detail. You should see the loading spinner for 5 seconds then, before it resolves to <some value>.

Does hubot have a similar feature/workaround to botkit's conversation feature? (& making hubot forget responses)

Mostly trying to check if what I am trying to do is possible as I have struggled to find any similar examples online.
I'm trying to create a series of menu's using hubot's framework so that individual commands and values do not have to be memorised. Instead you simply enter one command at the beginning, give relevant information once where these values will be stored for use multiple times later down the menus.
Something like this:
robot.hear /blah/i, id:'start', (msg) ->
currentPosition = 'start'
msg.send "Please select an Option"
selectOption msg
selectOption = (msg) ->
currentPosition = 'selectOption'
msg.send "Option 1"
msg.send "Option 2"
robot.hear /(.*)/i, id:'selectOption', (msg) ->
displayOption1 msg if msg.match is '1'
displayOption2 msg if msg.match is '2'
displayOption1 = (msg) ->
currentPosition = 'displayOption1'
msg.send "Please enter some information"
robot.hear /(.*)/i, id: 'displayOption1', (msg) ->
# if information is entered do something with information
# pass the information onto another method etc...
# ....
# methods to do something with information and feedback results
# ....
# ....
# methods corresponding to option 2
# ....
# ....
# methods to do something with information and feedback results
# ....
end = (msg) ->
currentPosition = 'none'
msg.send "Thank you for using our service"
I have been using listener middleware to make sure that you cannot access the menu's out of order:
robot.listenerMiddleware (context, next, done) ->
listenerID = context.listener.options?.id
return unless listenerID?
try
if listenerID is 'start'
if currentPosition is 'none'
next()
else
done()
if listenerID is 'selectOption'
if currentPosition is 'selectOption'
next()
# etc...
# Other similar examples to above for every "menu" ...
catch err
robot.emit ('error', err, context.response)
Everything seems to work as expected the first time I go through the menu's however the problems start if I try and launch from the start for a second time. Values seem to get remembered even if I set them to null at the start or end of my methods. And when I get closer to the end it will start printing out things twice.
I assume this is because values are getting cached/stored elsewhere and I need to reset this. I also assume that the reason it's printing out twice is because hubot remembers that I have already been through the menu's once and there's two instances running at once (it will start printing out three times if I go through a third time). However it only seems to do this towards the end and will print out as expected for the first few methods.
Simply, is there a way to make hubot forget everything perhaps in the 'end' method so it runs like I'm running it for the first time every time? I've looked into this but things like robot.shutdown don't seem to work.
If the above isn't possible, is there are workaround?
Edit: If it at all helps, I'm trying to make something similar to botkit's conversation feature: https://github.com/howdyai/botkit#multi-message-replies-to-incoming-messages
I got linked to this on my thread on github asking the same question:
https://github.com/lmarkus/hubot-conversation
Currently trying it out to see if it solves the issue I'm having, if not hopefully it will help out other people having a similar problem to me.

Remote Job execution with non terminating Return

I have a script that I am running both remotely and locally in different situations. In the remote situations I would like to return some additional job information. However, the script also needs to complete with a Restart, LogOff, etc.
However, if I Return $Results, no code that follows is executed. Whereas if I Write-Host the return info, I see it as additional data for the job, and the script completion code that follows can still execute.
I can make this work, but it causes two issues.
I have two bits of data I need to return, which I had planned to do in an array. But with Write-Host I need to use the kludge of $value1|$value2 and then split the string on | to get at the two bits of data.
Write-Host somewhat pollutes my console so I need some extra code to manage that.
Is there any way to return intermediate info and continue execution? Or am I going to have no choice but to go the Write-Host route? Or is there perhaps another approach that is better than the Write-Host hack?
You seem to be under the impression that you have to use the return keyword to make a function(?) return something. PowerShell works a little differently, though. PowerShell functions return the entire non-captured output on the success output stream. The return keyword is just for making a function return at that particular point.
There is no difference at all between
function Foo {
return 'something' # return with value
}
and
function Foo {
'something'
return # echo first, then return
}
and
function Foo {
'something' # just echo, return implicitly
}
That way you can have a function generate the output, then do more stuff before actually returning:
function Foo {
'foo'
'bar'
Get-ChildItem . -Recurse | Out-Null # output not returned (suppressed)
'baz' > 'C:\some.txt' # output not returned (redirected to file)
}
The caller will receive the returned values (in this case 'foo', 'bar') only after the function call returns, though. If you need immediate feedback you'll need other means.
Don't use Return. Just output $Results, and let the rest of the script continue on.