Trigger timer callback - google-cloud-dataflow

I have a stateful DoFn where I batch elements for a while and then use a timer to trigger a batch flush. Something like:
class BatchToPubSub(DoFn):
HEAP_STATE_SPEC = ReadModifyWriteStateSpec("events_heap", CDCEventHeapCoder())
TIMER = TimerSpec("timer", TimeDomain.WATERMARK)
BATCH_SIZE = 512
def process(
self,
element,
events_heap_state=DoFn.StateParam(HEAP_STATE_SPEC),
timer=DoFn.TimerParam(TIMER),
t=DoFn.TimestampParam,
):
_, event = element
events_heap = events_heap_state.read() or CDCEventHeap()
events_heap.push(event)
self.incoming_count.inc()
events_heap_state.write(events_heap)
if len(events_heap) >= self.BATCH_SIZE:
timer.set(time.time()) # here I want to force timer callback
# self.expire(...) manual call to callback
else:
timer.set(t + Duration(seconds=ALLOWED_LATENESS))
What is the best approach to trigger the callback by setting the timer? I've noticed that if set the timer to the current timestamp, the callback never gets triggered.
The other way of doing this is to manually call the callback and I'm fine with this, but I am thinking if it's better to make the timer trigger it?
Update add code for timer spec and state spec.

Related

Why is my timer's tolerance always halved?

In my app, I'm scheduling a timer like this:
let period = TimeInterval(10)
let timer = Timer.scheduledTimer(withTimeInterval: period, repeats: true, block: { [weak self] (_) in
// Some repeating code here
})
timer.tolerance = period
Essentially, I want a timer to fire once in every consecutive, repeating 10 second period, but it doesn't matter when the timer fires in each individual period. However, if I set a breakpoint in the debugger for immediately after this code runs. I can see that my timer's timeInterval is set to 10 seconds, but the timer's tolerance is set to 5. I've played around with various values for period, but no matter the case, it seems that my timer's tolerance will always be half of its timeInterval. Why is that? Will this still produce the functionality I intend? If not, how can I prevent this from happening?

How can I reload new JSON data from the same site in Swift?

basically i am making an app that pulls a number from online (using json) and what i want to know is how i can reload that data every 5 seconds or so. I have set it up so it is in a function called getData() and i thought making it in an infinite while loop would work like this:
while 1 > 0 {
getData()
sleep(5)
}
However, whenever i launch the app it crashes. (It works when i call getData() without the infinite loop) Am i missing something? How can i refresh my json data every 5 seconds? Thank You!
Apart from these you can use:
var timerDispatchSourceTimer : DispatchSourceTimer?
you can call your function in ViewWillAppear and set the delay as you want:
timerDispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
timerDispatchSourceTimer?.scheduleRepeating(deadline: .now(), interval: .seconds(YOUR DELAY TIME))
timerDispatchSourceTimer?.setEventHandler{
// do something here
self.performSelector(inBackground: #selector(YOUR FUNCTION), with: nil)
}
timerDispatchSourceTimer?.resume()
and on viewwillDisAppear:
timerDispatchSourceTimer?.cancel()

How to update variable based on an external event in Swift?

I am using a Particle Core to get the temperature from my room. The temperature is accessed through the cloud, which is being constantly updated in a variable. This is how I access the variable and display it:
func updateTemp(){
let seconds = 3.0
let delay = seconds * Double(NSEC_PER_SEC) // nanoseconds per seconds
let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
self.myPhoton?.getVariable("tempF", completion: { (result:AnyObject!, error:NSError!) -> Void in
if let _ = error {
print("Failed reading temperature from device")
}
else {
if let larry = result as? Int {
self.temp.text="\(larry)˚"
self.truth++ //Once a value has been found, update the count.
}
}
})
})
}
override func viewDidLoad() {
sparkStart()
}
override func viewDidLayoutSubviews() {
updateTemp()
NSTimer.scheduledTimerWithTimeInterval(100.0, target: self, selector: "updateTemp", userInfo: nil, repeats: true) //Gaurantees that the app is updated every 100 seconds. That way we have a fresh temperature often.
//Stop the spinning once a value has been found
if truth == 1{
activity.stopAnimating()
activity.removeFromSuperview()
}
}
Since this is my Particle Core detecting the temperature from environment, the temperature variable is constantly changing. However, when I use NSTimer, the code does not get updated in the time specified. Instead, it begins by updating based on the specified time, but then the time starts decreases exponentially and the variable is updated every 0.001 seconds or so. Any thoughts?
Im assuming what we see is not the full code. In your viewDidLayoutSubviews function, you call updateTemp twice. Once explicitly and once via timer callback.
Your updateTemp function schedules the network call in the main run loop, that's where the timer is also running. The dispatch_after function queues the execution of the readout updates one after the other. I am now assuming, that something in your display code causes repeated triggers of viewDidLayoutSubviews, each of which schedules two new updates etc. Even if the assumption is false (there are a couple of other possibilities due to network code being slow and the timer also running in the main run loop), I am guessing if you drop the explicit call to updateTemp you'll lose the "exponential" and should be fine.
In general, as the web call is largely asynchronous, you could just use the timer and call your sensor directly or if you feel GCD has an important performance advantage switch to dispatch_async and apply for the next available queue with each call via calling dispatch_get_global_queue

Subsequent WKInterfaceTime / NSTimer events with array of NSTimeInterval values

I am trying to run subsequent Timer events with WKInterfaceTimer & NSTimer, the problem is that I cannot figure out a way to make more than two subsequent calls with one NSTimer object. Basically, I would like run timer to complete then fire up the next.
Here's some sample code that hopefully explains my idea a little better....
1) I am firing off the first timer in awakeWithContext:
func initalTimer() {
let timer1String = NSMutableAttributedString(string: "Lap1")
runStatusLabel.setAttributedText(timerString)
myTimer = NSTimer.scheduledTimerWithTimeInterval(duration, target: self, selector: Selector("timerDone"), userInfo: nil, repeats: false)
runTimer.setDate(NSDate(timeIntervalSinceNow: duration))
runTimer.start()
}
NOTE: Everything works great at this point, then the tiemrDone function is called where I then fire off another timed event.
2)
func timerDone() {
//print("Done")
elapsedTime = 0.0
myTimer!.invalidate()
startTime = NSDate()
timeRunning = false
// Call second timed event
timer2() // just another NSTimer / WKInterfaceTimer function
}
"Stacking" the functions with a completionHandler does not seem to help OR most likely I am doing something wrong...
func execute_Timers(timeInterval: NSTimeInterval, completionHandler: (success: Bool, error: String?) -> Void ) -> Int {
// Code below never gets executed
}
I haven't tested this, and it is just a guess: When your timerDone() method is called, you invalidate the timer. Therefore it doesn't "complete," so your completion routine isn't called. When your timer completes, it gets invalidated anyway, so the call should not be needed. Try removing:
myTimer!.invalidate()
and see what happens.
Thanks for the reply, and you are quite correct - I do not need to call myTimer!.invalidate(). The solution that worked for me was to have different timerDone methods and conditionaly call the next time method.
-Paul

Actionscript settimeout not working

The Timer always jumps right into the function instead of waiting 2000 milliseconds
stop();
var hey:Number= 2000;
function exercise(frame) {
trace("sup");
this.gotoAndStop(frame);
}
setTimeout(exercise(2),hey);
trace(hey);
The setTimeout function (ie. not a Timer) takes the following parameters:
public function setTimeout(closure:Function, delay:Number, ... arguments):uint
Try:
// Save the return value so you can clear it later, otherwise your app for leak memory
var myTimeOut:uint = setTimeout(exercise, hey, 2);
trace(hey);
// the timeout closure object will not be garage collected if you do not clear it
clearTimeout(myTimeOut);
If you are doing this over and over, consider creating a Timer and setting/reseting the repeat count to 1 and then you can just restart the timer when need.

Resources