live 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08c6f4d6d5b5fc0e7ba635b617256c06ca84c925b528b99e4ab758bf6461af19'
4
- data.tar.gz: 69266f1a602d85f9f3d14104a2548304498ed38310f34ffa5dfe9e3e9d48aed6
3
+ metadata.gz: 63034baadcba271590245009b106e82bc142734cbc4978d7a47c264a8368d92c
4
+ data.tar.gz: ddb382c9499a3560ece8341a61e6d78076b2b2544fbb7ff3de1371e315e321bd
5
5
  SHA512:
6
- metadata.gz: a4e608d98be19c629dd8cba31cb5be8eeac52de4a5fb007ba4822f0baf8b473e16aa4db604585b8ff481d39292c2986408b2d3977667b77552de1cff31b4a85c
7
- data.tar.gz: 1fa963047b5369012f008c57061a585345d98922082d3c744b032ae15c8599a928f7a9c5b12169ac2242cb1f013b55404cce13f4cd4a2763259eda23b8fe06ac
6
+ metadata.gz: c8c7edabe0b494d83b0260e803cf39899eb4a2bd91a8eba9e714ccf255f23cd7bb76ee19df9811bc255f316cc113c67fa9814b0152fcd0d05382e3c5e8f93877
7
+ data.tar.gz: d4e8a3bfebf1bd77374cba4bac80d428b218834c2f0acb773268093aeb14ea14f3131194533c7a8aa0094431d20ee224f584d4babe6c27d9e7852119223cb578
checksums.yaml.gz.sig CHANGED
Binary file
data/lib/live/element.rb CHANGED
@@ -3,8 +3,8 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
- require 'json'
7
- require 'securerandom'
6
+ require "json"
7
+ require "securerandom"
8
8
 
9
9
  module Live
10
10
  class PageError < RuntimeError
@@ -79,7 +79,7 @@ module Live
79
79
  def rpc(*arguments)
80
80
  if @page
81
81
  # This update might not be sent right away. Therefore, mutable arguments may be serialized to JSON at a later time (or never). This could be a race condition:
82
- @page.updates.enqueue(arguments)
82
+ @page.enqueue(arguments)
83
83
  else
84
84
  # This is a programming error, as it probably means the element is still part of the logic of the server side (e.g. async loop), but it is not bound to a page, so there is nothing to update/access/rpc.
85
85
  raise PageError, "Element is not bound to a page, make sure to implement #close!"
data/lib/live/page.rb CHANGED
@@ -3,14 +3,16 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
- require_relative 'element'
7
- require_relative 'resolver'
6
+ require_relative "element"
7
+ require_relative "resolver"
8
8
 
9
- require 'async'
10
- require 'async/queue'
9
+ require "async"
10
+ require "async/queue"
11
11
 
12
- require 'protocol/websocket'
13
- require 'protocol/websocket/message'
12
+ require "protocol/websocket"
13
+ require "protocol/websocket/message"
14
+
15
+ require "console/event/failure"
14
16
 
15
17
  module Live
16
18
  # Represents a connected client page with bound dynamic content areas.
@@ -25,9 +27,6 @@ module Live
25
27
  @updates = Async::Queue.new
26
28
  end
27
29
 
28
- # The queue of outstanding events to be sent to the client.
29
- attr :updates
30
-
31
30
  # Bind a client-side element to a server side element.
32
31
  # @parameter element [Live::Element] The element to bind.
33
32
  def bind(element)
@@ -74,30 +73,38 @@ module Live
74
73
 
75
74
  def close
76
75
  @elements.each do |id, element|
77
- element.close
76
+ begin
77
+ element.close
78
+ rescue => error
79
+ Console::Event::Failure.for(error).emit(self)
80
+ end
78
81
  end
79
82
  end
80
83
 
84
+ def enqueue(update)
85
+ @updates.enqueue(::Protocol::WebSocket::TextMessage.generate(update))
86
+ end
87
+
81
88
  # Process a single incoming message from the network.
82
89
  def process_message(message)
83
90
  case message[0]
84
- when 'bind'
91
+ when "bind"
85
92
  # Bind a client-side element to a server-side element.
86
93
  if element = self.resolve(message[1], message[2])
87
94
  self.bind(element)
88
95
  else
89
96
  Console.warn(self, "Could not resolve element:", message)
90
- @updates.enqueue(['error', message[1], "Could not resolve element!"])
97
+ self.enqueue(["error", message[1], "Could not resolve element!"])
91
98
  end
92
- when 'unbind'
99
+ when "unbind"
93
100
  # Unbind a client-side element from a server-side element.
94
101
  if element = @elements.delete(message[1])
95
102
  element.close unless @attached.key?(message[1])
96
103
  else
97
104
  Console.warn(self, "Could not unbind element:", message)
98
- @updates.enqueue(['error', message[1], "Could not unbind element!"])
105
+ self.enqueue(["error", message[1], "Could not unbind element!"])
99
106
  end
100
- when 'event'
107
+ when "event"
101
108
  # Handle an event from the client.
102
109
  self.handle(message[1], message[2])
103
110
  else
@@ -107,22 +114,43 @@ module Live
107
114
 
108
115
  # Run the event handling loop with the given websocket connection.
109
116
  # @parameter connection [Async::WebSocket::Connection]
110
- def run(connection)
117
+ def run(connection, keep_alive: 10)
111
118
  Sync do |task|
119
+ last_update = Async::Clock.now
120
+
112
121
  queue_task = task.async do
113
122
  while update = @updates.dequeue
114
- Console.debug(self, "Sending update:", update)
115
- ::Protocol::WebSocket::TextMessage.generate(update).send(connection)
116
- connection.flush if @updates.empty?
123
+ update.send(connection)
124
+
125
+ # Flush the output if there are no more updates:
126
+ if @updates.empty?
127
+ connection.flush
128
+ end
129
+ end
130
+ end
131
+
132
+ keep_alive_task = task.async do
133
+ while true
134
+ sleep(keep_alive)
135
+
136
+ duration = Async::Clock.now - last_update
137
+
138
+ # We synchronize all writes to the update queue:
139
+ if duration > keep_alive
140
+ @updates.enqueue(::Protocol::WebSocket::PingMessage.new)
141
+ end
117
142
  end
118
143
  end
119
144
 
120
145
  while message = connection.read
121
- Console.debug(self, "Reading message:", message)
146
+ last_update = Async::Clock.now
122
147
  process_message(message.parse)
123
148
  end
124
149
  ensure
150
+ keep_alive_task&.stop
151
+
125
152
  self.close
153
+
126
154
  queue_task&.stop
127
155
  end
128
156
  end
data/lib/live/resolver.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
- require_relative 'element'
6
+ require_relative "element"
7
7
 
8
8
  module Live
9
9
  # Resolves a client-side tag into a server-side instance.
data/lib/live/version.rb CHANGED
@@ -4,5 +4,5 @@
4
4
  # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
6
  module Live
7
- VERSION = "0.13.0"
7
+ VERSION = "0.14.0"
8
8
  end
data/lib/live/view.rb CHANGED
@@ -3,8 +3,8 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
- require_relative 'element'
7
- require 'xrb/builder'
6
+ require_relative "element"
7
+ require "xrb/builder"
8
8
 
9
9
  module Live
10
10
  # Represents a single division of content on the page an provides helpers for rendering the content.
@@ -12,7 +12,7 @@ module Live
12
12
  # @returns [Object] The generated HTML.
13
13
  def to_html
14
14
  XRB::Builder.fragment do |builder|
15
- builder.inline_tag :div, id: @id, class: 'live', data: @data do
15
+ builder.inline_tag :div, id: @id, class: "live", data: @data do
16
16
  render(builder)
17
17
  end
18
18
  end
data/lib/live.rb CHANGED
@@ -5,6 +5,6 @@
5
5
 
6
6
  require_relative "live/version"
7
7
 
8
- require_relative 'live/page'
9
- require_relative 'live/view'
10
- require_relative 'live/resolver'
8
+ require_relative "live/page"
9
+ require_relative "live/view"
10
+ require_relative "live/resolver"
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: live
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -39,7 +39,7 @@ cert_chain:
39
39
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
40
40
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
41
41
  -----END CERTIFICATE-----
42
- date: 2024-07-05 00:00:00.000000000 Z
42
+ date: 2024-09-25 00:00:00.000000000 Z
43
43
  dependencies:
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: async-websocket
@@ -55,6 +55,20 @@ dependencies:
55
55
  - - "~>"
56
56
  - !ruby/object:Gem::Version
57
57
  version: '0.27'
58
+ - !ruby/object:Gem::Dependency
59
+ name: protocol-websocket
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: '0.19'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '0.19'
58
72
  - !ruby/object:Gem::Dependency
59
73
  name: xrb
60
74
  requirement: !ruby/object:Gem::Requirement
metadata.gz.sig CHANGED
Binary file