Long running script that polls external server with variable backoff timer? - amphp

I am writing a long running script based on Amphp library, that will poll a external server for a list of tasks to run and then execute those tasks.
In the response from the server would be the backoff timer that would control when the script makes it's next request.
Since I am very new to async programming what I am trying is not working.
I tried to create a \Amp\repeat() that had an \Amp\Pause(1000) so that each repeat would pause for 1 second.
Here's my test code:
function test() {
// http request goes here...
echo 'server request '.microtime(true).PHP_EOL;
// based on the server request, change the pause time
yield new \Amp\Pause(1000);
}
Amp\execute(function () {
\Amp\onSignal(SIGINT, function () {
\Amp\stop();
});
\Amp\repeat(100, function () {
yield from test();
});
});
What I expected to happen was that on each repeat, the test() function would pause for 1 second after the echo but instead the echo was run every 100ms (the repeat time).
In the past I would accomplish this with a while loop and usleep() but since usleep() is blocking this defeats the purpose.
I'm using PHP 7.0 and Amphp from github master branch.

\Amp\repeat calls the callback every 100 milliseconds, regardless of when the callback terminates.
\Amp\execute(function () {
/* onSignal handler here for example */
new \Amp\Coroutine(function () {
while (1) {
/* dispatch request */
echo 'server request '.microtime(true).PHP_EOL;
yield new \Amp\Pause(100);
}
});
});
This is using a normal loop which only continues 100 ms after the last action.
[If I misunderstood what exactly you want, please note in comments.]

Related

is requestAnimationFrame belong to microtask or macrotask in main thread task management? if not, how can we categorize this kind of render side task

how react schedule effects? I made some test, it seems hooks is called after requestAnimationFrame, but before setTimeout. So, I was wondering, how is the real implementation of scheduler. I checked react source code, it seems built upon MessageChannel api.
Also, how event-loop runs the macrotask sequence, for instance setTimeout/script etc.?
const addMessageChannel = (performWorkUntilDeadline: any) => {
const channel = new MessageChannel();
const port = channel.port2;
channel.port1.onmessage = performWorkUntilDeadline;
port.postMessage(null);
}
const Component1 = () => {
const [value,] = useState('---NOT INITIALISED')
requestIdleCallback(() => {
console.log('requestIdleCallback---')
})
useEffect(() => {
console.log('useEffect---')
}, [])
Promise.resolve().then(() => {
console.log('promise---')
})
setTimeout(() => {
console.log('setTimeout---')
});
addMessageChannel(()=> {
console.log('addMessageChannel---')
})
requestAnimationFrame(() => {
console.log('requestAnimationFrame---')
})
return <div>{value}</div>;
}
export default Component1
browser console result:
promise---
requestAnimationFrame---
addMessageChannel---
useEffect---
setTimeout---
requestIdleCallback---
I'm not sure about the useEffect so I'll take your word they use a MessageChannel and consider both addMessageChannel and useEffect a tie.
First the title (part of it at least):
[Does] requestAnimationFrame belong to microtask or macrotask[...]?
Technically... neither. requestAnimationFrame (rAF)'s callbacks are ... callbacks.
Friendly reminder that there is no such thing as a "macrotask": there are "tasks" and "microtasks", the latter being a subset of the former.
Now while microtasks are tasks they do have a peculiar processing model since they do have their own microtask-queue (which is not a task queue) and which will get visited several times during each event-loop iterations. There are multiple "microtask-checkpoints" defined in the event-loop processing model, and every time the JS callstack is empty this microtask-queue will get visited too.
Then there are tasks, colloquially called "macro-tasks" here and there to differentiate from the micro-tasks. Only one of these tasks will get executed per event-loop iteration, selected at the first step.
Finally there are callbacks. These may be called from a task (e.g when the task is to fire an event), or in some particular event-loop iterations, called "painting frames".
Indeed the step labelled update the rendering is to be called once in a while (generally when the monitor sent its V-Sync update), and will run a series of operations, calling callbacks, among which our dear rAF's callbacks.
Why is this important? Because this means that rAF (and the other callbacks in the "painting frame"), have a special place in the event-loop where they may seem to be called with the highest priority. Actually they don't participate in the task prioritization system per se (which happens in the first step of the event loop), they may indeed be called from the same event-loop iteration as even the task that did queue them.
setTimeout(() => {
console.log("timeout 1");
requestAnimationFrame(() => console.log("rAF callback"));
const now = performance.now();
while(performance.now() - now < 1000) {} // lock the event loop
});
setTimeout(() => console.log("timeout 2"));
Which we can compare with this other snippet where we start the whole thing from inside a rAF callback:
requestAnimationFrame(() => {
setTimeout(() => {
console.log("timeout 1");
requestAnimationFrame(() => console.log("rAF callback"));
});
setTimeout(() => console.log("timeout 2"));
});
While this may seem like an exceptional case to have our task called in a painting-frame, it's actually quite common, because browsers have recently decided to break rAF make the first call to rAF trigger a painting frame instantly when the document is not animated.
So any test with rAF should start long after the document has started, with an rAF loop already running in the background...
Ok, so rAF result may be fluck. What about your other results.
Promise first, yes. Not part of the task prioritization either, as said above the microtask-queue will get visited as soon as the JS callstack is empty, as part of the clean after running a script step.
rAF, fluck.
addMessageChannel, see this answer of mine. Basically, in Chrome it's due to both setTimeout having a minimum timeout of 1ms, and a higher priority of the message-tasksource over the timeout-tasksource.
setTimeout currently has a 1ms minimum delay in Chrome and a lower priority than MessageEvents, still it would not be against the specs to have it called before the message.
requestIdleCallback, that one is a bit complex but given it will wait for the event-loop has not done anything in some time, it will be the last.

How to pass variable from app.config() to app.run()

I am loading data (idle time and timeout time) from the database via rest api call. From frontend side I am using AngularJs 1.3.1 $http get call to get the data.
I need the above data (idle time and timeout time) at the app.config() level --- which is working fine.
I need to pass the same data (idle time and timeout time) from app.config() to app.run(). Any idea how to do that?
Also how to make sure $http get call is completed and idle time and timeout time is fetched from the database before idle time and timeout time is sent to app.run()?
I hope people will understand the question and respond to it. I am stuck at it right now.
code block:
angular.module().config(function() {
var idleWarnTime, idleTimeOut;
var http = angular.injector([ 'ng' ]).get('$http');
http.get('timeout').success(function(response) {
idleWarnTime = response.data.warntime;
idleTimeOut = response.data.timeout;
}).error(function(error) {
console.log('session timeout details fetching from db failed');
});
});
angular.module().run(function() {
//need idleWarnTime and idleTimeOut values here and only after "timeout" rest api provide the result
});

Akka.net - Streams with parallelism, backpressure and ActorRef

Tying to learn how use Akka.net Streams to process items in parallel from a Source.Queue, with the processing done in an Actor.
I've been able to get it to work with calling a function with Sink.ForEachParallel, and it works as expected.
Is it possible to process items in parallel with Sink.ActorRefWithAck (as I would prefer it utilize back-pressure)?
About to press Post, when tried to combine previous attempts and viola!
Previous attempts with ForEachParallel failed when I tried to create the actor within, but couldn't do so in an async function. If I use an single actor previous declared, then the Tell would work, but I couldn't get the parallelism I desired.
I got it to work with a router with roundrobin configuration.
var props = new RoundRobinPool(5).Props(Props.Create<MyActor>());
var actor = Context.ActorOf(props);
flow = Source.Queue<Element>(2000,OverflowStrategy.Backpressure)
.Select(x => {
return new Wrapper() { Element = x, Request = ++cnt };
})
.To(Sink.ForEachParallel<Wrapper>(5, (s) => { actor.Tell(s); }))
.Run(materializer);
The Request ++cnt is for console output to verify the requests are being processed as desired.
MyActor has a long delay on every 10th request to verify the backpressure was working.

$timeout.flush during protractor test [duplicate]

I'm testing my angular application with Protractor.
Once the user is logged in to my app, I set a $timeout to do some job in one hour (so if the user was logged-in in 13:00, the $timeout will run at 14:00).
I keep getting these failures:
"Timed out waiting for Protractor to synchronize with the page after 20 seconds. Please see https://github.com/angular/protractor/blob/master/docs/faq.md. The following tasks were pending: - $timeout: function onTimeoutDone(){....."
I've read this timeouts page: https://github.com/angular/protractor/blob/master/docs/timeouts.md
so I understand Protractor waits till the page is fully loaded which means he's waiting for the $timeout to complete...
How can I make Protractor NOT wait for that $timeout?
I don't want to use:
browser.ignoreSynchronization = true;
Because then my tests will fail for other reasons (other angular components still needs the time to load...)
The solution will be to flush active timeouts (as #MBielski mentioned it in comments), but original flush method itself is available only in anuglar-mocks. To use angular-mocks directly you will have to include it on the page as a <script> tag and also you'll have to deal with all overrides it creates, it produces a lot of side effects. I was able to re-create flush without using angular-mocks by listening to any timeouts that get created and then reseting them on demand.
For example, if you have a timeout in your Angular app:
$timeout(function () {
alert('Hello World');
}, 10000); // say hello in 10 sec
The test will look like:
it('should reset timeouts', function () {
browser.addMockModule('e2eFlushTimeouts', function () {
angular
.module('e2eFlushTimeouts', [])
.run(function ($browser) {
// store all created timeouts
var timeouts = [];
// listen to all timeouts created by overriding
// a method responsible for that
var originalDefer = $browser.defer;
$browser.defer = function (fn, delay) {
// originally it returns timeout id
var timeoutId = originalDefer.apply($browser, arguments);
// store it to be able to remove it later
timeouts.push({ id: timeoutId, delay: delay });
// preserve original behavior
return timeoutId;
};
// compatibility with original method
$browser.defer.cancel = originalDefer.cancel;
// create a global method to flush timeouts greater than #delay
// call it using browser.executeScript()
window.e2eFlushTimeouts = function (delay) {
timeouts.forEach(function (timeout) {
if (timeout.delay >= delay) {
$browser.defer.cancel(timeout.id);
}
});
};
});
});
browser.get('example.com');
// do test stuff
browser.executeScript(function () {
// flush everything that has a delay more that 6 sec
window.e2eFlushTimeouts(6000);
});
expect(something).toBe(true);
});
It's kinda experimental, I am not sure if it will work for your case. This code can also be simplified by moving browser.addMockModule to a separate node.js module. Also there may be problems if you'd want to remove short timeouts (like 100ms), it can cancel currently running Angular processes, therefore the test will break.
The solution is to use interceptors and modify the http request which is getting timeout and set custom timeout to some milliseconds(your desired) to that http request so that after sometime long running http request will get closed(because of new timeout) and then you can test immediate response.
This is working well and promising.

Can protractor be made to run slowly?

Is there a way to run a Angular E2E test written using protractor slowly so that I can watch what is happening?
Below is my solution to do that. So basically I created a decorator for current control flow execute function, which now additionaly queues a delay of 100ms before each queued action.
This needs to be run before any tests are invoked (outside describe block)
var origFn = browser.driver.controlFlow().execute;
browser.driver.controlFlow().execute = function() {
var args = arguments;
// queue 100ms wait
origFn.call(browser.driver.controlFlow(), function() {
return protractor.promise.delayed(100);
});
return origFn.apply(browser.driver.controlFlow(), args);
};
Just like George Stocker said in the comment, I don't know why you would want to do this...but you can always add a sleep wherever you want in your test.
browser.sleep(6000);
Previous answers look more like workaround. Another way is to add param to Protractor config:
highlightDelay: 1000
And change to:
directConnect: false
It will delay Protractor actions like clicking or typing for 1 second and will highlight in light blue.
You can enter in 'debug mode' by placing in your code the command:
browser.pause();
In the debug mode, you would see the following output in your terminal:
------- WebDriver Debugger -------
ready
press c to continue to the next webdriver command
press d to continue to the next debugger statement
type "repl" to enter interactive mode
type "exit" to break out of interactive mode
press ^C to exit
You could then:
Run command by command by entering c
Continue to the next debugger statement (next browser.pause()) by entering d
Enter in interactive mode where you could interact with all the elements by entering repl
2 ways for doing this
1. First is very childish way, but I'll leave it here
you can highlight the elements you're interacting with!
highlightElement: async ($elementObject, time = 1000) => {
async function setStyle(element, style) {
const previous = await element.getAttribute('style');
await element.setAttribute('style', style);
await setTimeout(() => {
element.setAttribute('style', previous);
}, time);
}
await browser.sleep(time)
return await browser.executeScript(await setStyle, $elementObject.getWebElement(), 'color: red; background-color: yellow; z-index: 9999;');
},
This will highlight the element for a second
And then wrap your actions using this element
let click = async function ($elem) {
await highlightElement($elem);
await $elem.click();
}
let sendKeys = async function ($elem, text) {
await highlightElement($elem);
await $elem.sendKeys(text);
}
And then use it to try some scripts
await sendKeys($login, username);
await sendKeys($password, password);
await click($submit);
This shouldn't really be used in the real script, only when you're playing with it
2. Setup debugging configuration in your code editor
Example for vs code https://medium.com/#ganeshsirsi/how-to-debug-protractor-tests-in-visual-studio-code-e945fc971a74, but the same thing can be achieved in webstorm
This will allow you to execute the code line by line and interact with the variables in the real time. MUST HAVE for everyone who works with protractor. I'm serious

Resources