Skip to content

Commit be28f06

Browse files
committed
Fix handling of cancellation so that it just uses Future->done
1 parent 238e4dd commit be28f06

File tree

11 files changed

+232
-102
lines changed

11 files changed

+232
-102
lines changed

.vscode/settings.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
},
1313
"files.exclude": {
1414
"client/out": true, // set this to true to hide the "out" folder with the compiled JS files
15-
"client/dist": true // set this to true to hide the "dist" folder with the compiled JS files
15+
"client/dist": true, // set this to true to hide the "dist" folder with the compiled JS files
16+
"server/blib": true
1617
},
1718
"search.exclude": {
1819
"client/out": true, // set this to false to include "out" folder in search results
19-
"client/dist": true // set this to false to include "dist" folder in search results
20+
"client/dist": true, // set this to false to include "dist" folder in search results
21+
"server/blib": true
2022
},
2123
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
2224
"typescript.tsc.autoDetect": "off"

server/MANIFEST

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ lib/PLS/Server/Response/Resolve.pm
4545
lib/PLS/Server/Response/Location.pm
4646
lib/PLS/Server/Response/WorkspaceSymbols.pm
4747
lib/PLS/Server/Response/Shutdown.pm
48+
lib/PLS/Server/Response/Sleep.pm
4849
lib/PLS/Server/Request/Progress.pm
50+
lib/PLS/Server/Request/Sleep.pm
4951
lib/PLS/Server/Request/Window/WorkDoneProgress/Create.pm
5052
lib/PLS/Server/Response/InvalidRequest.pm
5153
lib/PLS/Server/Message.pm

server/lib/PLS/Server.pm

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -56,39 +56,34 @@ sub run
5656
$self->{stream} = IO::Async::Stream->new_for_stdio(
5757
autoflush => 0,
5858
on_read => sub {
59-
my $size = 0;
59+
my ($stream, $buffref, $eof) = @_;
6060

61-
return sub {
62-
my ($stream, $buffref, $eof) = @_;
61+
exit if $eof;
6362

64-
exit if $eof;
63+
my @futures;
6564

66-
if (not $size)
67-
{
68-
if (${$buffref} =~ s/^(.*?)\r\n\r\n//s)
69-
{
70-
my $headers = $1;
71-
72-
my %headers = map { split /: / } grep { length } split /\r\n/, $headers;
73-
$size = $headers{'Content-Length'};
74-
die 'no Content-Length header provided' unless $size;
75-
} ## end if (${$buffref} =~ s/^(.*?)\r\n\r\n//s...)
76-
else
77-
{
78-
return 0;
79-
}
80-
} ## end if (not $size)
65+
while (${$buffref} =~ s/^(.*?)\r\n\r\n//s)
66+
{
67+
my $headers = $1;
8168

82-
return 0 if (length(${$buffref}) < $size);
69+
my %headers = map { split /: / } grep { length } split /\r\n/, $headers;
70+
my $size = $headers{'Content-Length'};
71+
die 'no Content-Length header provided' unless $size;
8372

84-
my $json = substr ${$buffref}, 0, $size, '';
85-
$size = 0;
73+
if (length ${$buffref} < $size)
74+
{
75+
${$buffref} = "$headers\r\n\r\n${$buffref}";
76+
return 0;
77+
}
8678

79+
my $json = substr ${$buffref}, 0, $size, '';
8780
my $content = decode_json $json;
8881

89-
$self->handle_client_message($content);
90-
return 1;
91-
}; ## end sub
82+
push @futures, $self->handle_client_message($content);
83+
} ## end while (${$buffref} =~ s/^(.*?)\r\n\r\n//s...)
84+
85+
Future->wait_all(@futures)->get();
86+
return 0;
9287
}
9388
);
9489

@@ -127,11 +122,11 @@ sub handle_client_message
127122

128123
if ($message->isa('PLS::Server::Request'))
129124
{
130-
$self->handle_client_request($message);
125+
return $self->handle_client_request($message);
131126
}
132127
if ($message->isa('PLS::Server::Response'))
133128
{
134-
$self->handle_client_response($message);
129+
return $self->handle_client_response($message);
135130
}
136131

137132
return;
@@ -182,6 +177,7 @@ sub handle_client_request
182177
if ($response->isa('PLS::Server::Response'))
183178
{
184179
$self->send_message($response);
180+
return;
185181
}
186182
elsif ($response->isa('Future'))
187183
{
@@ -192,19 +188,15 @@ sub handle_client_request
192188
$self->{running_futures}{$id} = $response;
193189
}
194190

195-
$response->await();
191+
return $response->then(
192+
sub {
193+
my ($response) = @_;
196194

197-
if ($response->is_cancelled)
198-
{
199-
$response = PLS::Server::Response::Cancelled->new(id => $id);
200-
}
201-
else
202-
{
203-
$response = $response->result;
204-
}
205-
206-
delete $self->{running_futures}{$id};
207-
$self->send_message($response);
195+
delete $self->{running_futures}{$id};
196+
$self->send_message($response);
197+
return Future->done();
198+
}
199+
);
208200
} ## end elsif ($response->isa('Future'...))
209201

210202
return;
@@ -258,7 +250,7 @@ sub cancel_request
258250

259251
if (blessed($future) and $future->isa('Future'))
260252
{
261-
$future->cancel();
253+
$future->done(PLS::Server::Response::Cancelled->new(id => $id));
262254
}
263255

264256
return;

server/lib/PLS/Server/Method/ServerMethod.pm

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use PLS::Server::Request::Initialized;
99
use PLS::Server::Request::CancelRequest;
1010
use PLS::Server::Request::Shutdown;
1111
use PLS::Server::Request::Exit;
12+
use PLS::Server::Request::Sleep;
1213
use PLS::Server::Response::ServerNotInitialized;
1314
use PLS::Server::Response::InvalidRequest;
1415

@@ -86,6 +87,11 @@ sub get_request
8687
return PLS::Server::Request::CancelRequest->new($request);
8788
}
8889

90+
if ($method eq 'sleep')
91+
{
92+
return PLS::Server::Request::Sleep->new($request);
93+
}
94+
8995
if ($method eq 'shutdown')
9096
{
9197
return PLS::Server::Request::Shutdown->new($request);
@@ -98,11 +104,16 @@ sub is_server_method
98104
{
99105
my ($method) = @_;
100106

101-
return 1 if ($method eq 'initialize');
102-
return 1 if ($method eq 'initialized');
103-
return 1 if ($method eq 'shutdown');
104-
return 1 if ($method eq 'exit');
105-
return 1 if ($method eq '$');
107+
my %valid = (
108+
initialize => 1,
109+
initialized => 1,
110+
shutdown => 1,
111+
exit => 1,
112+
sleep => 1,
113+
'$' => 1
114+
);
115+
116+
return 1 if $valid{$method};
106117
return 0;
107118
} ## end sub is_server_method
108119

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package PLS::Server::Request::Sleep;
2+
3+
use strict;
4+
use warnings;
5+
6+
use parent 'PLS::Server::Request';
7+
8+
use IO::Async::Loop;
9+
use IO::Async::Timer::Countdown;
10+
11+
use PLS::Server::Response::Sleep;
12+
13+
sub service
14+
{
15+
my ($self) = @_;
16+
17+
return PLS::Server::Response::Sleep->new($self);
18+
}
19+
20+
1;

server/lib/PLS/Server/Response/DocumentSymbol.pm

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ use warnings;
55

66
use parent 'PLS::Server::Response';
77

8+
use IO::Async::Loop;
9+
use IO::Async::Timer::Countdown;
10+
811
use PLS::Parser::Document;
912
use PLS::Parser::DocumentSymbols;
1013

@@ -25,27 +28,55 @@ sub new
2528

2629
my $self = bless {id => $request->{id}, result => undef}, $class;
2730

28-
my $uri = $request->{params}{textDocument}{uri};
31+
my $uri = $request->{params}{textDocument}{uri};
32+
33+
# Document symbols are requested and canceled very often. We should wait to make sure
34+
# that we aren't requesting them too quickly.
35+
my $loop = IO::Async::Loop->new();
36+
my $future = $loop->new_future();
37+
my $timer = IO::Async::Timer::Countdown->new(delay => 2,
38+
on_expire => sub { $self->on_expire($uri, $future) });
39+
$timer->start();
40+
$loop->add($timer);
41+
42+
return $future;
43+
} ## end sub new
44+
45+
sub on_expire
46+
{
47+
my ($self, $uri, $future) = @_;
48+
49+
if ($future->is_ready)
50+
{
51+
return;
52+
}
53+
2954
my $version = PLS::Parser::Document::uri_version($uri);
3055

31-
return PLS::Parser::DocumentSymbols->get_all_document_symbols_async($uri)->then(
56+
PLS::Parser::DocumentSymbols->get_all_document_symbols_async($uri)->then(
3257
sub {
3358
my ($symbols) = @_;
3459

60+
if ($future->is_ready)
61+
{
62+
return Future->done();
63+
}
64+
3565
my $current_version = PLS::Parser::Document::uri_version($uri);
3666

3767
if (not length $current_version or length $version and $current_version > $version)
3868
{
39-
return $self;
69+
$future->done($self);
70+
return Future->done();
4071
}
4172

4273
$self->{result} = $symbols;
43-
return $self;
44-
},
45-
sub {
46-
return $self;
74+
$future->done($self);
75+
return Future->done();
4776
}
48-
);
49-
} ## end sub new
77+
)->get();
78+
79+
return;
80+
} ## end sub on_expire
5081

5182
1;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package PLS::Server::Response::Sleep;
2+
3+
use strict;
4+
use warnings;
5+
6+
use parent 'PLS::Server::Response';
7+
8+
use IO::Async::Loop;
9+
use IO::Async::Timer::Countdown;
10+
11+
sub new
12+
{
13+
my ($class, $request) = @_;
14+
15+
my $self = bless {
16+
id => $request->{id},
17+
result => undef
18+
}, $class;
19+
20+
my $loop = IO::Async::Loop->new();
21+
my $future = $loop->new_future();
22+
$future->set_label('sleep');
23+
my $timer = IO::Async::Timer::Countdown->new(
24+
delay => 10,
25+
on_expire => sub {
26+
$future->done($self);
27+
},
28+
remove_on_expire => 1
29+
);
30+
$timer->start();
31+
$loop->add($timer);
32+
33+
return $future;
34+
} ## end sub new
35+
36+
1;

0 commit comments

Comments
 (0)