I have two timeouts defined:
timeout A - every 30 seconds
timeout B - every 2 minutes
// scheduled for timeout A (every 30sec)
#Stateless
public class MyBeanA {
(...)
#Timeout
public void onTimeoutA(javax.ejb.Timer timer) {
// (...)
}
}
// scheduled for timeout B (every 2min)
#Stateless
public class MyBeanB {
(...)
#Timeout
public void onTimeoutB(javax.ejb.Timer timer) {
// (...)
}
}
It's easy to notice, that after every 2 minutes, both timeouts will be fired. I'd like to make sure that in this case, timeout A will be fired before timeout B:
(30sec): timeoutA, (60sec): timeoutA, (90sec): timeoutA, (120sec): timeoutA, timeoutB
Is it possible with standard EJB (3.0) Timer Service API?
My application server is JBoss.
Thanks in advance,
Piotr
There is no built-in way to order timers like that. You could do it manually:
Schedule a single-action timer for A in 30 seconds with info=1
Schedule an interval timer for B for 120 seconds
When A fires with info=1, schedule a single-action timer for A in 30 seconds with info=2
When A fires with info=2, schedule a single action timer for A in 30 seconds with info=3
When A fires with info=3, don't reschedule
When B fires, call A, then do the work for B. Schedule a single-action timer for A in 30 seconds with info=1
Solution I used is very similar to the one given by bkail.
There is one ejbTimeout() method scheduled to be fired every 30seconds. Timeout is scheduled with Serializable object containing counter:
createTimer(Date initialExpiration, long intervalDuration, Serializable info)
Every time ejbTimeout is called, counter is increased. If it reach 3, then method which should be fired after 2 minutes is invoked, and also counter is set back to 0. It works as below:
ejbTimeout after 30sec (counter == 0): call A(); counter++;
ejbTimeout after 30sec (counter == 1): call A(); counter++;
ejbTimeout after 30sec (counter == 2): call A(); counter++;
ejbTimeout after 30sec (counter == 3): call A(); call B(); counter = 0;
Related
I'd like to kick off an HttpRequest and then poll for its completion. This feels like a fairly common pattern.
void main() {
_tick(0);
_tickB(0);
build();
print("End of main");
}
void build() {
var path = '../layout.txt';
html.HttpRequest.getString(path).then((String layout) {
print("layout received");
});
}
void _tick(int i) {
print("A $i");
if (i < 10) incr(i).then(_tick);
}
void _tickB(int i) {
print("B $i");
if (i < 10) incr(i).then(_tickB);
}
Future<int> incr(int i) async {
i++;
return i;
}
Output:
A1
B1
End of main
A2
B2
A3
B3
A4
B4
A5
B5
layout received
I would expect to see "layout received" appear interleaved with the other callbacks when the HttpRequest completes but its not. Its always (no matter the value of i, 5 is just a demo number) at the end of the interleaved callbacks.
Why is this?
How can I schedule the build callback in such a way that it completes during the other callback chains?
Your incr function doesn't actually do any asynchronous work. incr will be executed to completion immediately. Since the returned Future is already complete, its Future.then callbacks then will be scheduled in the microtask queue. Only after the microtask queue is empty will the separate event queue be processed. Your _tick/_tickB functions therefore create a (temporary) live-lock situation by repeatedly adding events to the microtask queue and preventing your HttpRequest Future from completing.
You can get the behavior you expect by making incr do some asynchronous work:
Future<int> incr(int i) async {
await Future.delayed(Duration.zero);
i++;
return i;
}
and then your output will be:
A 0
B 0
End of main
A 1
B 1
layout received
A 2
B 2
A 3
B 3
...
Further reading: The Event Loop and Dart
I would like to set a Timer in Event time that fires based on the smallest timestamp seen in the elements within my DoFn.
For performance reasons the Timer API does not support a read() operation, which for the vast majority of use cases is not a required feature. In the small set of use cases where it is needed, for example when you need to set a Timer in EventTime based on the smallest timestamp seen in the elements within a DoFn, we can make use of a State object to keep track of the value.
Java (SDK 2.10.0)
// In this pattern, a Timer is set to fire based on the lowest timestamp seen in the DoFn.
public class SetEventTimeTimerBasedOnEarliestElementTime {
private static final Logger LOG = LoggerFactory
.getLogger(SetEventTimeTimerBasedOnEarliestElementTime.class);
public static void main(String[] args) {
// Create pipeline
PipelineOptions options = PipelineOptionsFactory.
fromArgs(args).withValidation().as(PipelineOptions.class);
// We will start our timer at a fixed point
Instant now = Instant.parse("2000-01-01T00:00:00Z");
// ----- Create some dummy data
// Create 3 elements, incrementing by 1 minute
TimestampedValue<KV<String, Integer>> time_1 = TimestampedValue.of(KV.of("Key_A", 1), now);
TimestampedValue<KV<String, Integer>> time_2 = TimestampedValue
.of(KV.of("Key_A", 2), now.plus(Duration.standardMinutes(1)));
TimestampedValue<KV<String, Integer>> time_3 = TimestampedValue
.of(KV.of("Key_A", 3), now.plus(Duration.standardMinutes(2)));
Pipeline p = Pipeline.create(options);
// Apply a fixed window of duration 10 min and Sum the results
p.apply(Create.timestamped(time_3, time_2, time_1)).apply(
Window.<KV<String, Integer>>into(FixedWindows.<Integer>of(Duration.standardMinutes(10))))
.apply(ParDo.of(new StatefulDoFnThatSetTimerBasedOnSmallestTimeStamp()));
p.run();
}
/**
* Set timer to the lowest value that we see in the stateful DoFn
*/
public static class StatefulDoFnThatSetTimerBasedOnSmallestTimeStamp
extends DoFn<KV<String, Integer>, KV<String, Integer>> {
// Due to performance considerations there is no read on a timer object.
// We make use of this Long value to keep track.
#StateId("currentTimerValue") private final StateSpec<ValueState<Long>> currentTimerValue =
StateSpecs.value(BigEndianLongCoder.of());
#TimerId("timer") private final TimerSpec timer = TimerSpecs.timer(TimeDomain.EVENT_TIME);
#ProcessElement public void process(ProcessContext c,
#StateId("currentTimerValue") ValueState<Long> currentTimerValue,
#TimerId("timer") Timer timer) {
Instant timeStampWeWantToSet = c.timestamp();
//*********** Set Timer
// If the timer has never been set then we set it.
// If the timer has been set but is larger than our current value then we set it.
if (currentTimerValue.read() == null || timeStampWeWantToSet.getMillis() < currentTimerValue
.read()) {
timer.set(timeStampWeWantToSet);
currentTimerValue.write(timeStampWeWantToSet.getMillis());
}
}
#OnTimer("timer") public void onMinTimer(OnTimerContext otc,
#StateId("currentTimerValue") ValueState<Long> currentTimerValue,
#TimerId("timer") Timer timer) {
// Reset the currentTimerValue
currentTimerValue.clear();
LOG.info("Timer # {} fired", otc.timestamp());
}
}
}
I've spent many hours looking for the solution, but since I am Dart begginer, I couldn't find it out by myself.
What I want to achieve is to create something like queue for some of the async functions that are called randomly (let's say, when user is tapping a button in my app) from different points in code while the app is running. I want them to be executed in the order they were called, so basically I have async methods such as updateDate() and updatePoints() and when the user is tapping button X the updateDate() is going to be called (added to queue), and similar with Y and updatePoints(). When the user taps i. e. X, X, Y I want to run updateDate(), updateDate(), updatePoints() in this exact order. When one task is complete, another one is starting. I guess I can't use await to achieve that. Any hints would be appreciated!
import 'dart:async';
import 'dart:collection';
import 'dart:math';
Future<void> main() async {
_simulateRealWork();
}
Scheduler _scheduler = Scheduler();
class Scheduler {
bool _scheduled = false;
Queue<Future Function()> _queue = Queue<Future Function()>();
void schedule(Future Function() task) {
_queue.add(task);
if (!_scheduled) {
_scheduled = true;
Timer(Duration(seconds: 0), _execute);
}
}
Future _execute() async {
while (true) {
if (_queue.isEmpty) {
_scheduled = false;
return;
}
var first = _queue.removeFirst();
await first();
}
}
}
void _simulateRealWork() {
var maxPeriod = 5;
var count = 5;
for (var i = 0; i < count; i++) {
print('Timer $i');
var random = Random();
Timer(Duration(seconds: random.nextInt(maxPeriod)), () {
print('Scheduled work $i');
Future work() async {
print('Started work $i');
await Future.delayed(Duration(seconds: random.nextInt(maxPeriod)));
print('Ended work $i');
}
_scheduler.schedule(work);
});
}
}
Result:
Timer 0
Timer 1
Timer 2
Timer 3
Timer 4
Scheduled work 2
Started work 2
Scheduled work 0
Scheduled work 3
Ended work 2
Started work 0
Scheduled work 1
Scheduled work 4
Ended work 0
Started work 3
Ended work 3
Started work 1
Ended work 1
Started work 4
Ended work 4
The following code might be a bad practice when used in large queue of tasks, but if you are sure that the array of tasks won't exceed an adequate size - this might work just fine:
Future<List<T>> runOneByOne<T>(List<T Function()> list) {
if (list.isEmpty) {
return Future.value(null);
}
Future task = Future<T>.microtask(list.first);
final List<T> results = [];
for (var i = 1; i < list.length; i++) {
final func = list[i];
task = task.then((res) { results.add(res); return Future<T>.microtask(func); });
}
return task.then((res) { results.add(res); return results; });
}
It executes functions one-by-one in the original order by wrapping one Future into another. results array is used to store returned values, returning all of the values in the end.
Execution stops and throws if stumbled upon an error. Results array is lost in that case. You can add try {...} closure to every microtask wrapper to ignore errors and return null in that one particular task, preserving other values in results array.
Usage example:
runOneByOne<int>([
() { print("First"); return 1; },
() { print("Second"); return 2; },
() { print("Third"); return 3; },
]).then((results) {
print(results); // List<int> [ 1, 2, 3 ]
});
inside my flutter app I want to check my api every 10 seconds. I found this post to run a function every x amount of time and did the following:
class _MainPage extends State<MainPage> {
int starter = 0;
void checkForNewSharedLists(){
// do request here
setState((){
// change state according to result of request
});
}
Widget build(BuildContext context) {
Timer.periodic(Duration(seconds: 15), (Timer t) => checkForNewSharedLists());
}
}
Unfortunately the requests pile up: after restarting the app on the first "round" there are two request to the api, the second round it's four requests, the third it's eight and so on...
Does anybody know how to fix this?
build() can and usually will be called more than once and every time a new Timer.periodic is created.
You need to move that code out of build() like
Timer? timer;
#override
void initState() {
super.initState();
timer = Timer.periodic(Duration(seconds: 15), (Timer t) => checkForNewSharedLists());
}
#override
void dispose() {
timer?.cancel();
super.dispose();
}
Even better would be to move out such code from widgets entirely in an API layer or similar and use a StreamBuilder to have the view updated in case of updated data.
Use Cron lib which will be run periodically, but there is a difference between Timer and Cron,
Timer: It's running a task on given specific time intervals whether it is seconds, minutes, or hours.
Cron: It's used for more complex time intervals, eg: if a task needs to be run on a specific time of an hour. let's see the diagram
The above diagram has an asterisk that represents a number that appears in a specific position.
import 'package:cron/cron.dart';
main() {
var cron = new Cron();
cron.schedule(new Schedule.parse('*/3 * * * *'), () async {
print('every three minutes');
});
cron.schedule(new Schedule.parse('8-11 * * * *'), () async {
print('between every 8 and 11 minutes');
});
}
The above examples are taken from the repository which pretty well explains that the first '*' represents minutes, similar for the hour and so on as shown in the diagram.
Another example of the hour would be Schedule.parse(* 1,2,3,4 * * *), This schedule will run every minute every day during the hours of 1 AM, 2 AM, 3 AM, and 4 AM.
for more reference
https://code.tutsplus.com/tutorials/scheduling-tasks-with-cron-jobs--net-8800
Timer works fine, but you can also use Stream to execute a function periodicly:
final Stream _myStream =
Stream.periodic(const Duration(seconds: x), (int count) {
// Do something and return something here
});
see: https://api.flutter.dev/flutter/dart-async/Stream/Stream.periodic.html
I was looking for code to run a function every n amount of seconds for x seconds in total. Also I added functionality to cancel the timer if the periodic Function returns a success before the total timer elapsed. So here is how to solve that:
bool success = false;
bool done = false;
Future.delayed(const Duration(seconds: n), () {
done = true;
print("Timeout");
});
await Stream.periodic(const Duration(seconds: x)).takeWhile((_) => !done).forEach((_) async
{
success = await FunctionYouWantToExecutePeriodicly();
done = success; // only if you want to finish the function earlier
});
I am stuck trying to do something simple. I want to be able to count upwards until I click on the screen at which point i want the counting to stop. In reality the code itself will be carrying out complex AI calculations for a game, but first I want to understand how to control the while loop. In android this would be trivial.
Here is what my code looks like
bool OK = true;
main() async{
html.querySelector('#content').onMouseUp.listen((e){
OK = false;
});
await for(int i in naturals){
print(i);
await sleep();
}
}
Stream get naturals async* {
int k = 0; while (OK) { yield await k++; }
}
Future sleep() {
return new Future.delayed(const Duration(milliseconds: 1), () => "1");
}
I put the sleep() method in as a way to ensure that control is passed to the event loop.
Is it possible to control a while loop without the sleep() method?
update
Just enqueue to allow the event queue to process outstanding events without additional delay use
Future sleep() {
return new Future.delayed(Duration.ZERO);
}
original
JavaScript and therefore can't Dart have threads in the browser and you need to pass control back to the event queue to allow it to process other events like you do with sleep().
Another approach would be to use webworkers and run the heavy calculation in a background task (webworker) to keep the UI thread free to process user events. This way even additional CPU cores can be utilized which isn't possible when all code runs in the browsers UI thread.
I don't know how to create webworkers in Dart though except with Angular2 Dart Web workers in Angular 2 Dart where Angular does the initialization.
I don't think it's too difficult but I don't know any docs.
To provide a more general answer - instead of a loop, you want to schedule a sequence of future tasks that each executes one iteration or step of your AI code (or whatever background process you want to have running).
You can have the step task recursively schedule itself:
dynamic doSomething(_) {
print('Doing something ...');
if(!stop) {
new Future.delayed(delay, (){}).then(doSomething);
}
return null;
}
main() async {
doSomething(null);
}
Although I don't recommend doing this. It's awkward to control - the step code has to check a flag variable to see if it should continue or stop and it's free running.
Alternatively you could use a Timer:
void doSomething(Timer timer) {
print('Doing something ...');
}
main() async {
new Timer.periodic(delay, doSomething);
}
This is throttled at a constant rate and has a uniform time step, and is easier to stop (call cancel() on the timer).
Another approach might be to synchronize with the browser's draw refresh cycle by requesting future animation frames:
import 'dart:html';
doSomething(num delta) {
print('Doing something ...');
window.animationFrame.then(doSomething);
}
void main() {
window.animationFrame.then(doSomething);
}
Time steps are not constant but you get the time delta. The advantage of this approach is that animation frame futures will not be scheduled if the browser window is hidden.
See How do I drive an animation loop at 60fps with Dart?
Those are very simple examples. Setting up proper background processes for physics simulation and AI in web games is actually surprisingly (to me at least) non-trivial. Here are two resources I found helpful.
http://gameprogrammingpatterns.com/ - a nice free online book of game programming patterns. http://gameprogrammingpatterns.com/game-loop.html - chapter on game loops.
http://gafferongames.com/game-physics/fix-your-timestep/ - part of a sequence of articles on physics simulation in games.
Following all suggestions this is the code I have ended up with, putting the heavy lifting in a worker, with controllable stopping and starting. I have used simple counting to get this working, but this is being replaced with my complex AI game calculations.
This uses time slices of 100ms within a worker isolate, which can only be interrupted after it has finished the batch. This allows me complete freedom to have complex animations on the screen while all this hard work is being done.
import 'dart:html' as html;
import 'dart:isolate';
import 'dart:math';
SendPort worker;
bool working = false;
main() async{
await startWorker();
html.querySelector('#stage').onMouseUp.listen((e){
if(working)worker.send('stop');
else worker.send('go');
});
}
startWorker() async{
var response = new ReceivePort();
await Isolate.spawnUri(Uri.parse("worker.dart"), null ,response.sendPort)
.then((_) => response.listen((msg){
if(msg is SendPort) {
worker = msg;
}
else {
messageReceived(msg);
}
}));
}
messageReceived(String message){
switch (message){
case 'working': working = true;
break;
case 'idle': working = false;
break;
default : print(message);
break;
}
}
worker.dart
import 'dart:isolate';
import 'dart:async';
SendPort replyTo;
bool OK = false;
const timeSlice = 100;
main(List<String> args, SendPort reply) async{
var response = new ReceivePort();
reply.send(response.sendPort);
replyTo = reply;
response.listen((msg) => messageReceived(msg));
replyTo.send("Hello from worker. Click to start and stop me");
}
messageReceived(String message){
switch(message){
case 'stop':
replyTo.send('idle');
OK = false;
break;
case 'go':
replyTo.send('working');
go();
break;
}
}
go()async {
OK = true;
int i = 0;
batchJob(){
int startTime = new DateTime.now().millisecondsSinceEpoch;
int elapsed = 0;
while(elapsed < timeSlice){
i ++; // the central routine
elapsed = new DateTime.now().millisecondsSinceEpoch - startTime;
}
}
while(OK){
batchJob();
replyTo.send(i.toString());
await new Future.delayed(const Duration(milliseconds: 0), () {});
}
}