Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
W
webapp-lib
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
CS-214
ul2024
webapp-lib
Commits
060e8e3b
Commit
060e8e3b
authored
4 months ago
by
Clément Pit-Claudel
Browse files
Options
Downloads
Patches
Plain Diff
client: Automatically reconnect if websocket connection drops
parent
036f3c83
No related branches found
No related tags found
1 merge request
!38
Customizable homepage + automatic reconnection
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
js/src/main/scala/cs214/webapp/client/StateMachineClientApp.scala
+46
-8
46 additions, 8 deletions
...ain/scala/cs214/webapp/client/StateMachineClientApp.scala
jvm/src/main/scala/cs214/webapp/server/web/ServerApp.scala
+1
-1
1 addition, 1 deletion
jvm/src/main/scala/cs214/webapp/server/web/ServerApp.scala
with
47 additions
and
9 deletions
js/src/main/scala/cs214/webapp/client/StateMachineClientApp.scala
+
46
−
8
View file @
060e8e3b
...
...
@@ -9,23 +9,61 @@ import org.scalajs.dom
type
Target
=
dom
.
Element
private
class
WebSocket
(
endpoint
:
String
)
:
var
socket:
Option
[
dom.WebSocket
]
=
None
val
MIN_DELAY_MS
=
10d
val
MAX_DELAY_MS
=
5000d
var
reconnect_delay_ms
=
MIN_DELAY_MS
private
var
listeners
:
List
[
String
=>
Unit
]
=
Nil
def
addListener
(
listener
:
String
=>
Unit
)
=
listeners
=
listener
::
listeners
def
send
(
str
:
String
)
=
socket
match
case
Some
(
s
)
=>
s
.
send
(
str
)
case
None
=>
dom
.
window
.
alert
(
"Disconnected!"
)
private
def
onmessage
(
event
:
dom.MessageEvent
)
=
listeners
.
foreach
(
_
(
event
.
data
.
toString
))
private
def
reconnect
()
:
Unit
=
println
(
"[ws] Attempting to connect"
)
val
_socket
=
dom
.
WebSocket
(
endpoint
)
def
onopen
(
event
:
dom.Event
)
=
reconnect_delay_ms
=
MIN_DELAY_MS
println
(
"[ws] WebSocket connection opened"
)
def
onclose
(
event
:
dom.CloseEvent
)
=
if
socket
==
Some
(
_socket
)
then
socket
=
None
println
(
s
"[ws] WebSocket connection closed (${event.code}): ${event.reason}"
)
if
event
.
code
!=
1000
then
// Normal closure
dom
.
window
.
setTimeout
(()
=>
reconnect
(),
reconnect_delay_ms
)
reconnect_delay_ms
=
math
.
min
(
1.5
*
reconnect_delay_ms
,
MAX_DELAY_MS
)
def
onerror
(
event
:
dom.Event
)
=
println
(
s
"[ws] WebSocket error"
)
_socket
.
close
(
3000
)
// Lowest custom error code
_socket
.
onopen
=
evt
=>
onopen
(
evt
)
_socket
.
onclose
=
evt
=>
onclose
(
evt
)
_socket
.
onerror
=
evt
=>
onerror
(
evt
)
_socket
.
onmessage
=
msg
=>
onmessage
(
msg
)
socket
=
Some
(
_socket
)
reconnect
()
abstract
class
WSClientApp
extends
ClientApp
:
WebClient.register
(
this
)
protected
def
init
(
userId:
UserId
,
sendMessage:
ujson.Value
=>
Unit
,
target
:
Target
)
:
ClientAppInstance
def
init
(
instanceId
:
InstanceId
,
userId
:
UserId
,
endpoint
:
String
,
target
:
Target
)
:
ClientAppInstance
=
val
socket
=
new
dom
.
WebSocket
(
endpoint
)
socket
.
onopen
=
(
event
:
dom.Event
)
=>
println
(
"WebSocket connection opened"
)
socket
.
onclose
=
(
event
:
dom.CloseEvent
)
=>
println
(
s
"WebSocket connection closed: ${event.reason}"
)
socket
.
onerror
=
(
event
:
dom.Event
)
=>
println
(
s
"WebSocket error: ${event.`type`}"
)
val
socket
=
WebSocket
(
endpoint
)
val
sendMessage
=
(
js
:
ujson.Value
)
=>
socket
.
send
(
js
.
toString
)
val
client
=
init
(
userId
,
sendMessage
,
target
)
socket
.
onmessage
=
msg
=>
val
js
=
ujson
.
read
(
msg
.
data
.
toString
)
socket
.
addListener
:
msg
=>
val
js
=
ujson
.
read
(
msg
)
client
.
onMessage
(
SocketResponseWire
.
decode
(
js
).
flatten
)
client
/** Instance of a client-side state machine application.
...
...
This diff is collapsed.
Click to expand it.
jvm/src/main/scala/cs214/webapp/server/web/ServerApp.scala
+
1
−
1
View file @
060e8e3b
...
...
@@ -100,7 +100,7 @@ private[web] abstract class ServerApp:
for
channels
<-
channels.values
channel
<-
channels
do
channel
.
send
(
cask
.
Ws
.
Close
())
channel
.
send
(
cask
.
Ws
.
Close
(
cask
.
Ws
.
Close
.
NormalClosure
,
"Shutdown"
))
/** Sends a message to a specific client. */
private
def
send
(
userId
:
UserId
)(
message
:
ujson.Value
)
:
Unit
=
instanceLock
.
synchronized
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment