Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/sse #258

Merged
merged 13 commits into from
Nov 5, 2017
Merged

Feature/sse #258

merged 13 commits into from
Nov 5, 2017

Conversation

ibelar
Copy link
Contributor

@ibelar ibelar commented Nov 2, 2017

Implementation of Server Side Event that allows developer to execute background tasks in PHP.

$bar = $app->add(['View', 'template' => new \atk4\ui\Template('<div id="{$_id}" class="ui teal progress">
  <div class="bar"></div>
  <div class="label">Testing SSE</div>
</div>')]);
$bar->js(true)->progress();

$button = $app->add(['Button', 'Turn On']);
// non-SSE way
//$button->on('click', $bar->js()->progress(['percent'=> 40]));

$button->on('click', $app->add('jsSSE')->set(function($sse) use ($bar) {

    $sse->send($bar->js()->progress(['percent'=> 33]));
    sleep(2);
    $sse->send($bar->js()->progress(['percent'=> 66]));
    sleep(2);
    
    // non-SSE way
    return $bar->js()->progress(['percent'=> 100]);

}));

Goal of this PR

Create a drop-in replacement for jsExpression (which is used quite widely in Agile UI) that is backward-compatible, but would provide interface for sending status updates on task completion.

@codecov
Copy link

codecov bot commented Nov 2, 2017

Codecov Report

Merging #258 into develop will decrease coverage by 2.08%.
The diff coverage is 0%.

Impacted file tree graph

@@              Coverage Diff              @@
##             develop     #258      +/-   ##
=============================================
- Coverage      73.47%   71.38%   -2.09%     
- Complexity      1076     1099      +23     
=============================================
  Files             60       61       +1     
  Lines           2590     2663      +73     
=============================================
- Hits            1903     1901       -2     
- Misses           687      762      +75
Impacted Files Coverage Δ Complexity Δ
src/SSE.php 0% <0%> (ø) 23 <23> (?)
src/TableColumn/Status.php 78.12% <0%> (-6.25%) 10% <0%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update eda7615...bd4b422. Read the comment docs.

@codecov
Copy link

codecov bot commented Nov 2, 2017

Codecov Report

Merging #258 into develop will decrease coverage by 3.63%.
The diff coverage is 1.24%.

Impacted file tree graph

@@              Coverage Diff              @@
##             develop     #258      +/-   ##
=============================================
- Coverage      73.47%   69.84%   -3.64%     
- Complexity      1076     1110      +34     
=============================================
  Files             60       62       +2     
  Lines           2590     2729     +139     
=============================================
+ Hits            1903     1906       +3     
- Misses           687      823     +136
Impacted Files Coverage Δ Complexity Δ
src/jsSSE.php 0% <0%> (ø) 18 <18> (?)
src/SSE.php 0% <0%> (ø) 23 <23> (?)
src/jsCallback.php 27.14% <6.25%> (+0.47%) 29 <16> (-7) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update eda7615...f8485c7. Read the comment docs.

@romaninsh
Copy link
Member

romaninsh commented Nov 3, 2017

Hey Alain. Pretty through implementation, but needs to be slightly refactored. There is wrong implementation fundamentally. Let me explain.

SSE is basically allows you to establish connection from the browser to the server. Should server close the connection, browser will re-connect, but connection should remain open for as long as possible. While connection is maintained, it can be used to deliver events. so $send should perform "echo" and "flush" but it should keep running.

Normally SSE could be used for a social site to alway have one connections for all users and notify browser about posts and such. This could be pretty neat with Chat applications too. But PHP is not very well suited for those uses, PHP has limit on a run-time, its connections are expensive etc so we don't really want to use SSE for THOES purposes.

For us the SSE have a different use pattern. It is to establish connection to perform a complex task which, lets say, takes 10 seconds to complete.

$sse = $button->add('SSE')->set(function ($sse) use ($button) {

    for ($i = 1; $i<10; $i++) {
        sleep(1);
        $sse->send($button->js()->set(rand(1, 100));
    }
});

In this particular case, once the connection is terminated, it should not be reconnected. The send() would emit javascript and the browser should execute it immediately, so you would see button change it's label 10 times with just 1 SSE connection, then it would stop.

I'd also like to see SSE to extend 'jsCallback' class instead of rendering itself. Technically we can emit Action "jsReload" which will send re-render of any object we want, since SSE is just a vehicle.

http://agile-ui.readthedocs.io/en/latest/callbacks.html?highlight=jscallback#jscallback

With that our new jsSSE class could be a drop-in replacement for Callback:

$label = $app->add('Label');
$cb = $label->add('jsSSE');

$cb->set(function($sse, $arg1){

    return 'width is '.$arg1;

}, [new \atk4\ui\jsExpression( '$(window).width()' )]);

$label->detail = $cb->getURL();
$label->js('click', $cb);

The difference is that we can use interface of $sse to send more expressions from inside callback:

$label = $app->add('Label');
$cb = $label->add('jsSSE');

$cb->set(function($sse, $arg1){
    $sse->send(new jsNotify('Process started'));
    sleep(2);
    $sse->send(new jsNotify('Almost there'));
    sleep(2);
    $sse->send(new jsNotify('DONE'));

    return 'width is '.$arg1;

}, [new \atk4\ui\jsExpression( '$(window).width()' )]);

$label->detail = $cb->getURL();
$label->js('click', $cb);

I'll try to create a very basic reference implementation of jsSSE class. I have also updated the description of this PR.

@@ -117,8 +79,62 @@ public function set($callback, $args = [])
$m = new Message($e->getMessage());
$m->addClass('error');

$this->app->terminate(json_encode(['success' => false, 'message' => $m->getHTML()]));
$this->terminate($m->getHTML(), false);
// TODO, may have a bug here? passing HTML as ajaxec?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ibelar - can you check?

@romaninsh romaninsh merged commit ef7e34c into develop Nov 5, 2017
@romaninsh romaninsh deleted the feature/sse branch November 5, 2017 15:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants