live 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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