board-sse-linuxfr.org 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 925a0bf418e17a5510f79d790a3fa57a7447826f018f8e0ce3324915541c48b0
4
+ data.tar.gz: 59c5e8491520cc9aac3eeb1f2b604745da9d81941d2e5d1c5ec61bdc831bf5d7
5
+ SHA512:
6
+ metadata.gz: 3ccb985f2211d416c0f5da6074388f5493fed88a3a4404a2ac1936dca19b73c9f7ac518bb5faf58e4f610760568da79ceb6c05816b74bd1efa9a6389f00679e3
7
+ data.tar.gz: dc85525402ec6339c2237c9f612c3174ad642a55182e3c0f392a66e1bd5b0fc0db98c3b94b4af71ee56697218b5fd5a1603fcfa2307608c4b9e58941a1e3d26e
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "board-sse-linuxfr.org"
@@ -0,0 +1,35 @@
1
+ class BoardSseLinuxfrOrg
2
+ class Cache
3
+ CAPACITY = 10
4
+
5
+ class Entry < Array
6
+ def push(item)
7
+ super item
8
+ shift if size > CAPACITY
9
+ end
10
+
11
+ def from(id, &blk)
12
+ found = false
13
+ each do |item|
14
+ blk.call item if found
15
+ found ||= item.first == id
16
+ end
17
+ end
18
+ end
19
+
20
+ def initialize
21
+ @keys = Entry.new
22
+ @vals = Entry.new
23
+ end
24
+
25
+ def [](key)
26
+ n = @keys.index(key)
27
+ unless n
28
+ @keys.push key
29
+ @vals.push Entry.new
30
+ n = @keys.length - 1
31
+ end
32
+ @vals[n]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,40 @@
1
+ require "hiredis"
2
+ require "em-synchrony"
3
+ require "redis"
4
+ require "redis/connection/synchrony"
5
+ require "board-sse-linuxfr.org/cache"
6
+
7
+
8
+ class BoardSseLinuxfrOrg
9
+ class RedisPlugin
10
+ def initialize(address, port, config, status, logger)
11
+ logger.info "Initializing the Redis plugin"
12
+ @logger = logger
13
+ @chans = status[:channels] = Hash.new { |h,k| h[k] = EM::Channel.new }
14
+ @cache = status[:cache] = Cache.new
15
+ @redis = Redis.new(host: ENV['REDIS_HOST'] || "localhost", port: ENV['REDIS_PORT'] || 6379)
16
+ end
17
+
18
+ def run
19
+ EM.synchrony do
20
+ @redis.psubscribe("b/*") do |on|
21
+ on.psubscribe do |pattern, total|
22
+ @logger.info "Psubscribe to redis: #{pattern} (#{total})"
23
+ end
24
+
25
+ on.pmessage do |pattern, chan, msg|
26
+ _, chan, id = *chan.split('/')
27
+ @logger.info "New message: [#{chan.inspect}] #{id}. #{msg}"
28
+ [@chans, @cache].each do |storage|
29
+ storage[chan].push [id, msg]
30
+ end
31
+ end
32
+
33
+ on.punsubscribe do |pattern, total|
34
+ @logger.info "Punsubscribe to redis: #{pattern} (#{total})"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ class BoardSseLinuxfrOrg
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,33 @@
1
+ require "goliath"
2
+ require "yajl"
3
+
4
+
5
+ class BoardSseLinuxfrOrg < Goliath::API
6
+ autoload :Cache, "board-sse-linuxfr.org/cache"
7
+ autoload :RedisPlugin, "board-sse-linuxfr.org/redis_plugin"
8
+ autoload :VERSION, "board-sse-linuxfr.org/version"
9
+
10
+ plugin RedisPlugin
11
+
12
+ def response(env)
13
+ env.logger.info "New client: #{env['PATH_INFO']}"
14
+ send_msg = ->(args) {
15
+ id, msg = *args
16
+ env.stream_send("data: #{args.last}\nid: #{args.first}\n\n")
17
+ env.stream_close if env['HTTP_X_REQUESTED_WITH']
18
+ }
19
+ event_id = env['HTTP_LAST_EVENT_ID']
20
+ chan_name = env['PATH_INFO'].split('/', 3).last
21
+ env['cache'] = status[:cache][chan_name]
22
+ env['chan'] = status[:channels][chan_name]
23
+ env['sid'] = env['chan'].subscribe &send_msg
24
+ env['timer'] = EM.add_periodic_timer(15) { env.stream_send "::\n\n" }
25
+ EM.next_tick { env['cache'].from(event_id, &send_msg) } if event_id
26
+ streaming_response(200, {'Content-Type' => 'text/event-stream'})
27
+ end
28
+
29
+ def on_close(env)
30
+ env['chan'].unsubscribe env['sid'] if env['sid']
31
+ env['timer'].cancel if env['timer']
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: board-sse-linuxfr.org
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Bruno Michel
8
+ - Adrien Dorsaz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2024-03-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: goliath
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.0'
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.7
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '1.0'
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.7
34
+ - !ruby/object:Gem::Dependency
35
+ name: hiredis
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.4'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.4'
48
+ - !ruby/object:Gem::Dependency
49
+ name: redis
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: yajl-ruby
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2'
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.2'
76
+ - !ruby/object:Gem::Dependency
77
+ name: minitest
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.3'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.3'
90
+ description: |
91
+ Users of the LinuxFr.org website can chat on a space called the board (« la tribune » in french).
92
+ This Ruby daemon notifies the users when something is said with Server-Sent Event / EventSource.
93
+ email: adrien@adorsaz.ch
94
+ executables:
95
+ - board-sse-linuxfr.org
96
+ extensions: []
97
+ extra_rdoc_files: []
98
+ files:
99
+ - bin/board-sse-linuxfr.org
100
+ - lib/board-sse-linuxfr.org.rb
101
+ - lib/board-sse-linuxfr.org/cache.rb
102
+ - lib/board-sse-linuxfr.org/redis_plugin.rb
103
+ - lib/board-sse-linuxfr.org/version.rb
104
+ homepage: https://github.com/linuxfrorg/board-sse-linuxfr.org
105
+ licenses:
106
+ - AGPL-3.0-only
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.5.3
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Board for LinuxFr.org
127
+ test_files: []