Skip to content

Commit f459a74

Browse files
authored
Merge branch 'master' into dependabot/bundler/actionpack-7.2.2.1
2 parents e0fde7c + 8356c71 commit f459a74

File tree

8 files changed

+152
-35
lines changed

8 files changed

+152
-35
lines changed

Dockerfile

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
FROM alpine:3.20 AS alpine
22

3-
FROM ubuntu:20.04 AS bbb-playback
3+
FROM ubuntu:22.04 AS bbb-playback
44
ENV DEBIAN_FRONTEND=noninteractive
55
RUN apt-get update \
66
&& apt-get install -y language-pack-en \
77
&& update-locale LANG=en_US.UTF-8
88
ENV LANG=en_US.UTF-8
99
RUN apt-get update \
1010
&& apt-get install -y software-properties-common curl net-tools nginx
11-
RUN add-apt-repository -y ppa:bigbluebutton/support
12-
13-
RUN apt-get update \
11+
RUN add-apt-repository -y ppa:rmescandon/yq \
12+
&& apt-get update \
1413
&& apt-get install -y yq
1514
RUN curl -sL https://ubuntu.bigbluebutton.org/repo/bigbluebutton.asc | apt-key add - \
16-
&& echo "deb https://ubuntu.bigbluebutton.org/focal-260 bigbluebutton-focal main" >/etc/apt/sources.list.d/bigbluebutton.list
15+
&& echo "deb https://ubuntu.bigbluebutton.org/jammy-300 bigbluebutton-jammy main" >/etc/apt/sources.list.d/bigbluebutton.list
1716
RUN useradd --system --user-group --home-dir /var/bigbluebutton bigbluebutton
1817
RUN touch /.dockerenv
1918
RUN apt-get update \

Gemfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ GEM
134134
minitest (5.25.1)
135135
minitest-stub_any_instance (1.0.3)
136136
msgpack (1.7.0)
137-
net-imap (0.5.1)
137+
net-imap (0.5.6)
138138
date
139139
net-protocol
140140
net-pop (0.1.2)
@@ -144,7 +144,7 @@ GEM
144144
net-smtp (0.5.0)
145145
net-protocol
146146
nio4r (2.7.3)
147-
nokogiri (1.17.2)
147+
nokogiri (1.18.3)
148148
mini_portile2 (~> 2.8.2)
149149
racc (~> 1.4)
150150
parallel (1.22.1)
@@ -157,7 +157,7 @@ GEM
157157
puma (6.4.3)
158158
nio4r (~> 2.0)
159159
racc (1.8.1)
160-
rack (3.1.8)
160+
rack (3.1.12)
161161
rack-session (2.0.0)
162162
rack (>= 3.0.0)
163163
rack-test (2.1.0)
@@ -266,7 +266,7 @@ GEM
266266
tty-screen (= 0.8.1)
267267
unicode-display_width (~> 2.2)
268268
thor (1.3.2)
269-
timeout (0.4.2)
269+
timeout (0.4.3)
270270
tty-screen (0.8.1)
271271
tzinfo (2.0.6)
272272
concurrent-ruby (~> 1.0)

app/models/server.rb

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -286,24 +286,37 @@ def self.find(id)
286286
end
287287

288288
# Find the server with the lowest load (for creating a new meeting)
289-
def self.find_available(tag_arg = nil)
290-
# Check if tag is required
291-
tag = tag_arg.presence
292-
tag_required = false
293-
if !tag.nil? && tag[-1] == '!'
294-
tag = tag[0..-2].presence # always returns String, if tag is String
295-
tag_required = true
289+
def self.find_available(tags_arg = nil)
290+
# Check if passed tags are required
291+
tags_arg = tags_arg.presence
292+
tags_required = false
293+
if !tags_arg.nil? && tags_arg[-1] == '!'
294+
tags_arg = tags_arg[0..-2].presence # always returns String, if tag is String
295+
tags_required = true unless tags_arg.nil?
296296
end
297+
tags = tags_arg&.split(';')
297298

298299
# Find available&matching server with the lowest load
299300
with_connection do |redis|
300301
ids_loads = redis.zrange('server_load', 0, -1, with_scores: true)
301302
raise RecordNotFound.new("Could not find any available servers.", name, nil) if ids_loads.blank?
302-
if !tag.nil? && ids_loads.none? { |myid, _| redis.hget(key(myid), 'tag') == tag }
303-
raise BBBErrors::ServerTagUnavailableError, tag if tag_required
304-
tag = nil # fall back to servers without tag
303+
304+
# build a list of matching tagged servers, otherwise fall back to untagged
305+
unless tags.nil?
306+
ids_loads_tagged = []
307+
tags.each do |tag|
308+
ids_loads_tagged.concat ids_loads.select { |myid, _| (redis.hget(key(myid), 'tag') || "none") == tag }
309+
end
310+
ids_loads_tagged.sort_by! { |id_load| id_load[1] }
305311
end
306-
ids_loads = ids_loads.select { |myid, _| redis.hget(key(myid), 'tag') == tag }
312+
if ids_loads_tagged.blank?
313+
raise BBBErrors::ServerTagUnavailableError, tags_arg if tags_required
314+
tags = nil # fall back to servers without tag
315+
ids_loads_tagged = ids_loads.select { |myid, _| redis.hget(key(myid), 'tag').nil? }
316+
end
317+
ids_loads = ids_loads_tagged
318+
319+
# try to select the server with lowest load
307320
id, load, hash = ids_loads.each do |id, load|
308321
hash = redis.hgetall(key(id))
309322
break id, load, hash if hash.present?
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
FROM alpine:3.20 AS alpine
22

3-
FROM ubuntu:20.04 AS bbb-playback
3+
FROM ubuntu:22.04 AS bbb-playback
44
ENV DEBIAN_FRONTEND=noninteractive
55
RUN apt-get update \
66
&& apt-get install -y language-pack-en \
77
&& update-locale LANG=en_US.UTF-8
88
ENV LANG=en_US.UTF-8
99
RUN apt-get update \
1010
&& apt-get install -y software-properties-common curl net-tools nginx
11-
RUN add-apt-repository -y ppa:bigbluebutton/support
12-
13-
RUN apt-get update \
11+
RUN add-apt-repository -y ppa:rmescandon/yq \
12+
&& apt-get update \
1413
&& apt-get install -y yq
1514
RUN curl -sL https://ubuntu.bigbluebutton.org/repo/bigbluebutton.asc | apt-key add - \
16-
&& echo "deb https://ubuntu.bigbluebutton.org/focal-260 bigbluebutton-focal main" >/etc/apt/sources.list.d/bigbluebutton.list
15+
&& echo "deb https://ubuntu.bigbluebutton.org/jammy-300 bigbluebutton-jammy main" >/etc/apt/sources.list.d/bigbluebutton.list
1716
RUN useradd --system --user-group --home-dir /var/bigbluebutton bigbluebutton
1817
RUN touch /.dockerenv
1918
RUN apt-get update \
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
FROM amazonlinux:2.0.20240620.0 AS amazonlinux
22
SHELL ["/bin/bash", "-c"]
33

4-
FROM ubuntu:20.04 AS bbb-playback
4+
FROM ubuntu:22.04 AS bbb-playback
55
ENV DEBIAN_FRONTEND=noninteractive
66
RUN apt-get update \
77
&& apt-get install -y language-pack-en \
88
&& update-locale LANG=en_US.UTF-8
99
ENV LANG=en_US.UTF-8
1010
RUN apt-get update \
1111
&& apt-get install -y software-properties-common curl net-tools nginx
12-
RUN add-apt-repository -y ppa:bigbluebutton/support
13-
14-
RUN apt-get update \
12+
RUN add-apt-repository -y ppa:rmescandon/yq \
13+
&& apt-get update \
1514
&& apt-get install -y yq
1615
RUN curl -sL https://ubuntu.bigbluebutton.org/repo/bigbluebutton.asc | apt-key add - \
17-
&& echo "deb https://ubuntu.bigbluebutton.org/focal-260 bigbluebutton-focal main" >/etc/apt/sources.list.d/bigbluebutton.list
16+
&& echo "deb https://ubuntu.bigbluebutton.org/jammy-300 bigbluebutton-jammy main" >/etc/apt/sources.list.d/bigbluebutton.list
1817
RUN useradd --system --user-group --home-dir /var/bigbluebutton bigbluebutton
1918
RUN touch /.dockerenv
2019
RUN apt-get update \

docs/tags-README.md

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,30 @@ This works for all supported ways of adding servers: Per `rake servers:add` task
1212

1313
## Create call with server-tag metaparameter
1414

15-
A create API call with a meta feature is supposed to work as follows:
15+
A create API call using this feature is supposed to work as follows:
1616

17-
1) When making a "create" API call towards Scalelite, you can optionally pass a meta_server-tag string as parameter. If passed, it will be handled as follows:
18-
2) If the last character of meta_server-tag is not a '!', the tag will will be intepreted as *optional*. The meeting will be created on the lowest load server with the corresponding tag, if any is available, or on the lowest load untagged (i.e. tag == nil) server otherwise.
19-
3) If the last character of meta_server-tag is a '!', this character will be stripped and the remaining tag will be interpreted as *required*. The meeting will be created on the lowest load server with the corresponding tag or fail to be created (with specific error message), if no matching server is available.
17+
1) When making a "create" API call towards Scalelite, you can optionally pass a meta_server-tag parameter with a string value. The string can be a single tag or a semicolon-separated list of tags and may additionally contain a '!' as last character. It will be handled as follows:
18+
2) If the last character of meta_server-tag is not a '!', the tags will will be intepreted as *optional*. The meeting will be created on the least loaded server with a tag matching one of the passed tags (the special tag 'none' will match untagged servers), if any is available, or on the least loaded untagged server otherwise.
19+
3) If the last character of meta_server-tag is a '!', this character will be stripped and the remaining tags will be interpreted as *required*. The meeting will be created on the least loaded server with a tag matching one of the passed tags (the special tag 'none' will match untagged servers) or *fail* to be created (with a specific error message), if no matching server is available.
2020

2121
NOTE: Create calls without or with ''/'!' as meta_server-tag will only match untagged servers. So, for a frontend unaware of the feature, SL will behave as previously if a pool of untagged ("default") servers is maintained. It is recommended to always add your default servers as untagged servers.
2222

23+
### Examples
24+
25+
Consider the following setup:
26+
`$ bundle exec rake status`
27+
```
28+
HOSTNAME STATE STATUS MEETINGS USERS LARGEST MEETING VIDEOS LOAD BBB VERSION TAG
29+
bbb-1 enabled online 1 2 2 0 3.0 3.0.0 test
30+
bbb-2 enabled online 1 1 1 0 2.0 3.0.0
31+
bbb-3 enabled online 0 0 0 0 0.0 3.0.0
32+
bbb-4 enabled online 1 1 1 0 2.0 3.0.0 test2
33+
```
34+
35+
Now, consider the following examples of `meta_server-tag` parameters:
36+
- Passing `meta_server-tag=` or `meta_server-tag=!` or omitting the parameter altogether are all equivalent and will place the meeting on `bbb-3` (least loaded untagged).
37+
- Passing `meta_server-tag=test` or `meta_server-tag=test!` will place the meeting on `bbb-1` (the only match).
38+
- Passing `meta_server-tag=test;test2` or `meta_server-tag=test;test2!` will place the meeting on `bbb-4` (least loaded match).
39+
- Passing `meta_server-tag=none` or `meta_server-tag=none!` will place the meeting on `bbb-3` ) (least loaded match).
40+
- Passing `meta_server-tag=test3` will place the meeting on `bbb-3` (fallback to least loaded untagged).
41+
- Passing `meta_server-tag=test3!` will place the meeting on `bbb-3` (fallback to least loaded untagged).

spec/models/server_spec.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,22 @@
339339
expect(server.id).to eq 'test-3'
340340
end
341341
end
342+
343+
context 'and with none tag argument' do
344+
let(:server) { described_class.find_available('none') }
345+
346+
it 'returns untagged server with lowest load' do
347+
expect(server.id).to eq 'test-3'
348+
end
349+
end
350+
351+
context 'and with none! tag argument' do
352+
let(:server) { described_class.find_available('none!') }
353+
354+
it 'returns untagged server with lowest load' do
355+
expect(server.id).to eq 'test-3'
356+
end
357+
end
342358
end
343359

344360
context 'with differently tagged servers' do
@@ -366,6 +382,11 @@
366382
redis.sadd?('servers', 'test-4')
367383
redis.sadd?('server_enabled', 'test-4')
368384
redis.zadd('server_load', 1, 'test-4')
385+
redis.mapped_hmset('server:test-5', url: 'https://test-5.example.com/bigbluebutton/api', secret: 'test-5-secret',
386+
tag: 'test-tag2', enabled: 'true')
387+
redis.sadd?('servers', 'test-5')
388+
redis.sadd?('server_enabled', 'test-5')
389+
redis.zadd('server_load', 1, 'test-5')
369390
end
370391
end
371392

@@ -391,6 +412,29 @@
391412
expect(server.tag).to eq 'test-tag'
392413
end
393414
end
415+
416+
context 'and optional tag list argument' do
417+
let(:server) { described_class.find_available('test-tag;test-tag2') }
418+
419+
it 'returns matching tagged server with lowest load' do
420+
expect(server.id).to eq 'test-5'
421+
expect(server.url).to eq 'https://test-5.example.com/bigbluebutton/api'
422+
expect(server.secret).to eq 'test-5-secret'
423+
expect(server.tag).to eq 'test-tag2'
424+
expect(server.enabled).to be true
425+
expect(server.state).to be_nil
426+
expect(server.load).to eq 1
427+
end
428+
end
429+
430+
context 'and required tag list argument' do
431+
let(:server) { described_class.find_available('test-tag;test-tag2!') }
432+
433+
it 'returns matching tagged server with lowest load' do
434+
expect(server.id).to eq 'test-5'
435+
expect(server.tag).to eq 'test-tag2'
436+
end
437+
end
394438
end
395439

396440
context 'with no matching tagged servers' do

test/models/server_test.rb

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ class ServerTest < ActiveSupport::TestCase
243243
end
244244
end
245245

246-
test 'Server find_available without or with empty tag returns untagged server with lowest load' do
246+
test 'Server find_available without or with empty tag or with none tag returns untagged server with lowest load' do
247247
RedisStore.with_connection do |redis|
248248
redis.mapped_hmset('server:test-1', url: 'https://test-1.example.com/bigbluebutton/api', secret: 'test-1-secret',
249249
tag: 'test-tag', enabled: 'true')
@@ -276,6 +276,12 @@ class ServerTest < ActiveSupport::TestCase
276276

277277
server = Server.find_available('!')
278278
assert_equal('test-3', server.id)
279+
280+
server = Server.find_available('none')
281+
assert_equal('test-3', server.id)
282+
283+
server = Server.find_available('none!')
284+
assert_equal('test-3', server.id)
279285
end
280286

281287
test 'Server find_available with tag argument returns matching tagged server with lowest load' do
@@ -316,6 +322,44 @@ class ServerTest < ActiveSupport::TestCase
316322
assert_equal('test-tag', server.tag)
317323
end
318324

325+
test 'Server find_available with multiple tag arguments returns matching tagged server with lowest load' do
326+
RedisStore.with_connection do |redis|
327+
redis.mapped_hmset('server:test-1', url: 'https://test-1.example.com/bigbluebutton/api', secret: 'test-1-secret',
328+
enabled: 'true')
329+
redis.sadd?('servers', 'test-1')
330+
redis.sadd?('server_enabled', 'test-1')
331+
redis.zadd('server_load', 1, 'test-1')
332+
redis.mapped_hmset('server:test-2', url: 'https://test-2.example.com/bigbluebutton/api', secret: 'test-2-secret',
333+
tag: 'test-tag', enabled: 'true')
334+
redis.sadd?('servers', 'test-2')
335+
redis.sadd?('server_enabled', 'test-2')
336+
redis.zadd('server_load', 3, 'test-2')
337+
redis.mapped_hmset('server:test-3', url: 'https://test-3.example.com/bigbluebutton/api', secret: 'test-3-secret',
338+
tag: 'test-tag2', enabled: 'true')
339+
redis.sadd?('servers', 'test-3')
340+
redis.sadd?('server_enabled', 'test-3')
341+
redis.zadd('server_load', 2, 'test-3')
342+
redis.mapped_hmset('server:test-4', url: 'https://test-4.example.com/bigbluebutton/api', secret: 'test-4-secret',
343+
tag: 'wrong-tag', enabled: 'true')
344+
redis.sadd?('servers', 'test-4')
345+
redis.sadd?('server_enabled', 'test-4')
346+
redis.zadd('server_load', 1, 'test-4')
347+
end
348+
349+
server = Server.find_available('test-tag;test-tag2')
350+
assert_equal('test-3', server.id)
351+
assert_equal('https://test-3.example.com/bigbluebutton/api', server.url)
352+
assert_equal('test-3-secret', server.secret)
353+
assert_equal('test-tag2', server.tag)
354+
assert(server.enabled)
355+
assert_nil(server.state)
356+
assert_equal(2, server.load)
357+
358+
server = Server.find_available('test-tag;test-tag2!')
359+
assert_equal('test-3', server.id)
360+
assert_equal('test-tag2', server.tag)
361+
end
362+
319363
test 'Server find_available with optional tag returns untagged server with lowest load if no matching tagged server available' do
320364
RedisStore.with_connection do |redis|
321365
redis.mapped_hmset('server:test-1', url: 'https://test-1.example.com/bigbluebutton/api', secret: 'test-1-secret',

0 commit comments

Comments
 (0)