glottis 0.1.3 → 0.3.1

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
- SHA1:
3
- metadata.gz: 7a42b6e38fd2d75e8acbdc2dcf338453c34b69c7
4
- data.tar.gz: 189a29629e5104997a16071815febe031ee1e794
2
+ SHA256:
3
+ metadata.gz: 4f9b168031125cddf48f2087d3e3cd6c849e9a16972866b21db5d38c9cd2f83e
4
+ data.tar.gz: 64495dc081d2130d83ab6f3992e6f40de2bcdde85e65c0b3580cd46adcbf4af5
5
5
  SHA512:
6
- metadata.gz: 1cffde427455b740691132995a39ac6c1071a23f19bcef3744971958d414967c13ea4c9f28dabd521eef21dda5c074951dd311ee109ac81c6c4420514e1c253d
7
- data.tar.gz: 22dd5726fef0948fd4c114dddaa52c02a01699bbbcbe155e15622fc0c7f2b59474ae2bbf2689cbc133fdba2590c0e2ff97bc7ec602d468d67749bf9dc15a5eab
6
+ metadata.gz: ef03824e6fc0c56a6d1df2a93965f851b1795a9892c9bc35a404cd795514f0a692bdb4dcfdcd6b06896f61241fb4010186395b1d845c88a896a709bef6c3c5d9
7
+ data.tar.gz: 77c0d6bd62771b0fd28af07625ef8f1cedb986655ff68eb9bb0260c92beb47ca1b26c42f0b0cc482b6bb503599363e5daa81304546a8680865d073476329d613
data/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semmle.com/semver/1.0.0/).
7
+
8
+ ## [0.3.1] - 2026-07-24
9
+
10
+ ### Changed
11
+ - Bumped required Ruby version to `>= 3.0.0`.
12
+ - Removed `rb-readline` dependency in favor of Ruby standard library `reline`/`readline`.
13
+ - Updated `slop` runtime dependency to `~> 4.10`.
14
+ - Explicitly set `Content-Type: application/json` headers on outgoing HTTP request posts.
15
+ - Modernized gemspec metadata and file list configuration.
16
+ - Updated RuboCop configuration for Ruby 3.0+ compatibility (`Layout/LineLength`).
17
+ - Migrated CI from Travis CI to GitHub Actions (`.github/workflows/ci.yml`).
18
+
19
+ ### Added
20
+ - Comprehensive RSpec test suite covering core client, handlers, and live HTTP mock server integration.
data/README.md CHANGED
@@ -2,26 +2,47 @@
2
2
 
3
3
  A CLI for the [valyx](https://github.com/maxdeliso/valyx) message passing server.
4
4
 
5
+ [![CI](https://github.com/maxdeliso/glottis/actions/workflows/ci.yml/badge.svg)](https://github.com/maxdeliso/glottis/actions/workflows/ci.yml)
6
+ [![Gem Version](https://badge.fury.io/rb/glottis.svg)](https://badge.fury.io/rb/glottis)
7
+
8
+ ## Requirements
9
+
10
+ - Ruby >= 3.0.0
11
+
5
12
  ## Installation
6
13
 
14
+ Install the gem by executing:
15
+
7
16
  $ gem install glottis
8
17
 
18
+ Or add it to your application's Gemfile:
19
+
20
+ $ gem 'glottis', '~> 0.3'
21
+
9
22
  ## Usage
10
23
 
11
- $ glottis -h
24
+ Run the `glottis` command-line executable:
25
+
26
+ $ glottis --host localhost --port 8080
27
+
28
+ For help and available command line flags:
29
+
30
+ $ glottis --help
12
31
 
13
32
  ## Development
14
33
 
15
- To check the code:
34
+ To run the test suite and linter:
16
35
 
17
- $ bundle exec rake
36
+ $ bundle exec rake
18
37
 
19
38
  To install this gem onto your local machine:
20
39
 
21
- $ bundle exec rake install
40
+ $ bundle exec rake install
22
41
 
23
42
  ## Contributing
24
43
 
25
44
  Bug reports and pull requests are welcome on GitHub at https://github.com/maxdeliso/glottis.
26
45
 
27
- [![Gem Version](https://badge.fury.io/rb/glottis.svg)](https://badge.fury.io/rb/glottis)
46
+ ## License
47
+
48
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,6 +1,10 @@
1
- require 'bundler/gem_tasks'
2
- require 'rubocop/rake_task'
3
-
4
- RuboCop::RakeTask.new(:rubocop)
5
-
6
- task default: [:rubocop]
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rubocop/rake_task'
5
+ require 'rspec/core/rake_task'
6
+
7
+ RuboCop::RakeTask.new(:rubocop)
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ task default: %i[rubocop spec]
data/exe/glottis CHANGED
@@ -1,22 +1,23 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'slop'
4
- require 'glottis'
5
-
6
- opts = Slop.parse do |o|
7
- o.string '--host', 'a hostname', default: 'localhost'
8
- o.integer '--port', 'TCP port', default: 8080
9
- o.bool '-v', '--verbose', 'enable verbose mode'
10
- o.on '-V', '--version', 'print the version' do
11
- puts "glottis #{Glottis::VERSION}"
12
- exit
13
- end
14
- o.on '-h', '--help' do
15
- puts o
16
- exit
17
- end
18
- end
19
-
20
- Glottis::Client.new(opts[:host],
21
- opts[:port],
22
- verbose: opts[:verbose]).run
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'slop'
5
+ require 'glottis'
6
+
7
+ opts = Slop.parse do |o|
8
+ o.string '--host', 'a hostname', default: 'localhost'
9
+ o.integer '--port', 'TCP port', default: 8080
10
+ o.bool '-v', '--verbose', 'enable verbose mode'
11
+ o.on '-V', '--version', 'print the version' do
12
+ puts "glottis #{Glottis::VERSION}"
13
+ exit
14
+ end
15
+ o.on '-h', '--help' do
16
+ puts o
17
+ exit
18
+ end
19
+ end
20
+
21
+ Glottis::Client.new(opts[:host],
22
+ opts[:port],
23
+ verbose: opts[:verbose]).run
data/glottis.gemspec CHANGED
@@ -1,5 +1,6 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'glottis/version'
5
6
 
@@ -11,19 +12,26 @@ Gem::Specification.new do |spec|
11
12
  spec.licenses = ['MIT']
12
13
  spec.summary = 'simple http messaging client'
13
14
  spec.homepage = 'https://github.com/maxdeliso/glottis'
15
+ spec.required_ruby_version = '>= 3.0.0'
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/maxdeliso/glottis'
19
+ spec.metadata['changelog_uri'] = 'https://github.com/maxdeliso/glottis/blob/main/CHANGELOG.md'
20
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/maxdeliso/glottis/issues'
21
+ spec.metadata['rubygems_mfa_required'] = 'true'
14
22
 
15
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
- f.match(%r{^(test|spec|features)/})
17
- end
23
+ spec.files = Dir.glob('{exe,lib}/**/*').select { |f| File.file?(f) } +
24
+ %w[Rakefile README.md CHANGELOG.md glottis.gemspec]
18
25
 
19
26
  spec.bindir = 'exe'
20
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
28
  spec.require_paths = ['lib']
22
29
 
23
- spec.add_runtime_dependency 'rb-readline', '~> 0.5.3'
24
- spec.add_runtime_dependency 'slop', '~> 4.2'
30
+ spec.add_dependency 'slop', '~> 4.10'
25
31
 
26
- spec.add_development_dependency 'bundler', '~> 1.10'
27
- spec.add_development_dependency 'rake', '~> 10.0'
28
- spec.add_development_dependency 'rubocop', '~> 0.37.2'
32
+ spec.add_development_dependency 'bundler', '>= 2.0'
33
+ spec.add_development_dependency 'rake', '~> 13.0'
34
+ spec.add_development_dependency 'rspec', '~> 3.0'
35
+ spec.add_development_dependency 'rubocop', '~> 1.0'
36
+ spec.add_development_dependency 'webrick', '~> 1.8'
29
37
  end
@@ -1,4 +1,5 @@
1
- require 'thread'
1
+ # frozen_string_literal: true
2
+
2
3
  require 'logger'
3
4
  require 'glottis/handlers/console_input_handler'
4
5
  require 'glottis/handlers/console_output_handler'
@@ -6,10 +7,10 @@ require 'glottis/handlers/remote_input_handler'
6
7
  require 'glottis/handlers/remote_output_handler'
7
8
 
8
9
  module Glottis
9
- # Client class, used to interact with the host specified.
10
+ # Client class used to interact with the specified host and port.
10
11
  class Client
11
12
  def self.logger
12
- @logger ||= Logger.new(STDOUT)
13
+ @logger ||= Logger.new($stdout)
13
14
  end
14
15
 
15
16
  def initialize(host, port, opts = {})
@@ -17,13 +18,30 @@ module Glottis
17
18
  @port = port
18
19
  @outgoing = Queue.new
19
20
  @incoming = Queue.new
21
+ @handlers = []
20
22
  Client.logger.level = opts[:verbose] ? Logger::DEBUG : Logger::WARN
21
23
  end
22
24
 
23
25
  def run
24
26
  Client.logger.info('starting...')
25
- Thread.abort_on_exception = true
26
27
 
28
+ start_handlers
29
+ @handlers.each(&:join)
30
+ rescue Glottis::Exceptions::UserExitedException
31
+ Client.logger.info('User exited.')
32
+ rescue Interrupt
33
+ Client.logger.info('Received interrupt signal. Exiting...')
34
+ rescue Errno::ECONNREFUSED => e
35
+ Client.logger.error("Failed to connect to host: #{e.message}")
36
+ rescue StandardError => e
37
+ Client.logger.warn("Shutting down due to error: #{e.message}")
38
+ ensure
39
+ stop_handlers
40
+ end
41
+
42
+ private
43
+
44
+ def start_handlers
27
45
  @handlers = [
28
46
  Handlers::ConsoleInputHandler.new(@outgoing),
29
47
  Handlers::ConsoleOutputHandler.new(@incoming),
@@ -31,14 +49,11 @@ module Glottis
31
49
  Handlers::RemoteOutputHandler.new(@outgoing, @host, @port)
32
50
  ]
33
51
 
34
- @handlers.each(&:join)
35
- rescue Errno::ECONNREFUSED => conn_ref
36
- Client.logger.error("failed to connect: #{conn_ref}")
37
- rescue StandardError => ex
38
- Client.logger.warn("shutting down: #{ex}")
39
- ensure
52
+ @handlers.each(&:start)
53
+ end
54
+
55
+ def stop_handlers
40
56
  @handlers.each(&:cleanup)
41
- exit(0)
42
- end # run
43
- end # Client
57
+ end
58
+ end
44
59
  end
@@ -1,6 +1,8 @@
1
- module Glottis
2
- module Exceptions
3
- class GlottisException < StandardError
4
- end
5
- end
6
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Glottis
4
+ module Exceptions
5
+ class GlottisException < StandardError
6
+ end
7
+ end
8
+ end
@@ -1,8 +1,10 @@
1
- require 'glottis/exceptions/glottis_exception'
2
-
3
- module Glottis
4
- module Exceptions
5
- class UserExitedException < GlottisException
6
- end
7
- end
8
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'glottis/exceptions/glottis_exception'
4
+
5
+ module Glottis
6
+ module Exceptions
7
+ class UserExitedException < GlottisException
8
+ end
9
+ end
10
+ end
@@ -1,32 +1,52 @@
1
- require 'glottis/exceptions/user_exited_exception'
2
- require 'readline'
3
-
4
- module Glottis
5
- module Handlers
6
- # This class holds a reference to the outgoing message queue,
7
- # and posts messages to it from the console as they are entered.
8
- class ConsoleInputHandler < Thread
9
- USER_PROMPT = '> '.freeze
10
-
11
- def initialize(outgoing)
12
- @outgoing = outgoing
13
- super do
14
- loop do
15
- user_input = Readline.readline(USER_PROMPT)
16
- Readline::HISTORY.push(user_input)
17
-
18
- # if user_input.nil?
19
- # raise Glottis::Exceptions::UserExitedException.new
20
- # end
21
-
22
- @outgoing.push(user_input)
23
- end
24
- end
25
- end
26
-
27
- def cleanup
28
- # do nothing
29
- end
30
- end # ConsoleInputHandler
31
- end # Handlers
32
- end # Glottis
1
+ # frozen_string_literal: true
2
+
3
+ require 'glottis/exceptions/user_exited_exception'
4
+ require 'readline'
5
+
6
+ module Glottis
7
+ module Handlers
8
+ # Holds a reference to the outgoing message queue and posts console input.
9
+ class ConsoleInputHandler
10
+ USER_PROMPT = '> '
11
+
12
+ def initialize(outgoing)
13
+ @outgoing = outgoing
14
+ @running = false
15
+ @thread = nil
16
+ end
17
+
18
+ def start
19
+ @running = true
20
+ @thread = Thread.new { run_loop }
21
+ self
22
+ end
23
+
24
+ def join
25
+ @thread&.join
26
+ end
27
+
28
+ def cleanup
29
+ @running = false
30
+ @thread&.kill if @thread&.alive?
31
+ end
32
+
33
+ private
34
+
35
+ def run_loop
36
+ while @running
37
+ user_input = Readline.readline(USER_PROMPT, true)
38
+
39
+ if user_input.nil?
40
+ raise Glottis::Exceptions::UserExitedException,
41
+ 'User exited readline stream'
42
+ end
43
+
44
+ @outgoing.push(user_input)
45
+ end
46
+ rescue Glottis::Exceptions::UserExitedException => e
47
+ Client.logger.info("Console input ended: #{e.message}")
48
+ raise e
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,21 +1,40 @@
1
- module Glottis
2
- module Handlers
3
- # This class holds a reference to the incoming message queue,
4
- # and displays messages in the console as they are received.
5
- class ConsoleOutputHandler < Thread
6
- def initialize(incoming)
7
- @incoming = incoming
8
- super do
9
- loop do
10
- new_msg = @incoming.pop
11
- puts "#{new_msg['from']}, #{new_msg['to']}, #{new_msg['msg']}"
12
- end
13
- end
14
- end
15
-
16
- def cleanup
17
- puts '|'
18
- end
19
- end # ConsoleOutputHandler
20
- end # Handlers
21
- end # Glottis
1
+ # frozen_string_literal: true
2
+
3
+ module Glottis
4
+ module Handlers
5
+ # Holds a reference to incoming message queue and prints messages to stdout.
6
+ class ConsoleOutputHandler
7
+ def initialize(incoming)
8
+ @incoming = incoming
9
+ @running = false
10
+ @thread = nil
11
+ end
12
+
13
+ def start
14
+ @running = true
15
+ @thread = Thread.new { run_loop }
16
+ self
17
+ end
18
+
19
+ def join
20
+ @thread&.join
21
+ end
22
+
23
+ def cleanup
24
+ @running = false
25
+ @thread&.kill if @thread&.alive?
26
+ end
27
+
28
+ private
29
+
30
+ def run_loop
31
+ while @running
32
+ new_msg = @incoming.pop
33
+ break if new_msg.nil? || new_msg == :shutdown
34
+
35
+ puts "#{new_msg['from']}, #{new_msg['to']}, #{new_msg['msg']}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,53 +1,86 @@
1
- require 'logger'
2
- require 'uri'
3
- require 'net/http'
4
- require 'json'
5
-
6
- module Glottis
7
- module Handlers
8
- # This class manages a TCP connection with a valyx server.
9
- class RemoteInputHandler < Thread
10
- PROTOCOL = 'http'.freeze
11
- STREAM_DELIMITER = "\0".freeze
12
- READ_TIMEOUT = 3600 # this needs to be high
13
- REMOTE_PATHS = {
14
- get_message_stream: '/api/messages/stream'
15
- }.freeze
16
-
17
- def initialize(incoming, host, port)
18
- @incoming = incoming
19
- @host = host
20
- @port = port
21
-
22
- setup_http
23
-
24
- super do
25
- @http.start
26
- read_loop
27
- end
28
- end
29
-
30
- def cleanup
31
- @http.finish if @http.started?
32
- end
33
-
34
- private
35
-
36
- def setup_http
37
- @http = Net::HTTP.new(@host, @port)
38
- @http.open_timeout = 1
39
- @http.read_timeout = READ_TIMEOUT
40
- end
41
-
42
- def read_loop
43
- Client.logger.info('reading stream...')
44
- @http.get(REMOTE_PATHS.fetch(:get_message_stream)) do |chunk|
45
- Client.logger.debug("got chunk of length: #{chunk.length}")
46
- chunk.split(STREAM_DELIMITER).each do |msg_data|
47
- @incoming.push(JSON.parse(msg_data))
48
- end # each
49
- end # get
50
- end # read_loop
51
- end # RemoteInputHandler
52
- end # Handlers
53
- end # Glottis
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+ require 'uri'
5
+ require 'net/http'
6
+ require 'json'
7
+
8
+ module Glottis
9
+ module Handlers
10
+ # Manages stream input from the remote valyx server.
11
+ class RemoteInputHandler
12
+ PROTOCOL = 'http'
13
+ STREAM_DELIMITER = "\0"
14
+ READ_TIMEOUT = 3600
15
+ REMOTE_PATHS = {
16
+ get_message_stream: '/api/messages/stream'
17
+ }.freeze
18
+
19
+ def initialize(incoming, host, port)
20
+ @incoming = incoming
21
+ @host = host
22
+ @port = port
23
+ @running = false
24
+ @thread = nil
25
+ @buffer = String.new
26
+ setup_http
27
+ end
28
+
29
+ def start
30
+ @running = true
31
+ @thread = Thread.new do
32
+ @http.start
33
+ read_loop
34
+ end
35
+ self
36
+ end
37
+
38
+ def join
39
+ @thread&.join
40
+ end
41
+
42
+ def cleanup
43
+ @running = false
44
+ @http.finish if @http.started?
45
+ @thread&.kill if @thread&.alive?
46
+ end
47
+
48
+ private
49
+
50
+ def setup_http
51
+ @http = Net::HTTP.new(@host, @port)
52
+ @http.open_timeout = 1
53
+ @http.read_timeout = READ_TIMEOUT
54
+ end
55
+
56
+ def read_loop
57
+ Client.logger.info('reading stream...')
58
+ @http.get(REMOTE_PATHS.fetch(:get_message_stream)) do |chunk|
59
+ break unless @running
60
+
61
+ Client.logger.debug("got chunk of length: #{chunk.length}")
62
+ process_chunk(chunk)
63
+ end
64
+ rescue StandardError => e
65
+ Client.logger.error("Error reading message stream: #{e.message}") if @running
66
+ end
67
+
68
+ def process_chunk(chunk)
69
+ @buffer << chunk
70
+
71
+ while (delimiter_index = @buffer.index(STREAM_DELIMITER))
72
+ msg_raw = @buffer.slice!(0..delimiter_index)
73
+ msg_data = msg_raw.chomp(STREAM_DELIMITER)
74
+ next if msg_data.empty?
75
+
76
+ begin
77
+ parsed_msg = JSON.parse(msg_data)
78
+ @incoming.push(parsed_msg)
79
+ rescue JSON::ParserError => e
80
+ Client.logger.warn("Failed to parse JSON payload: #{e.message}")
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -1,87 +1,96 @@
1
- require 'logger'
2
- require 'uri'
3
- require 'net/http'
4
- require 'json'
5
-
6
- module Glottis
7
- module Handlers
8
- # This class manages a TCP connection with a valyx server.
9
- class RemoteOutputHandler < Thread
10
- POLL_INTERVAL = 0.1
11
- PROTOCOL = 'http'.freeze
12
-
13
- REMOTE_PATHS = {
14
- get_session: '/api/session',
15
- post_message: '/api/message'
16
- }.freeze
17
-
18
- def initialize(outgoing, host, port)
19
- @outgoing = outgoing
20
- @host = host
21
- @port = port
22
-
23
- setup_http
24
-
25
- super do
26
- @http.start
27
- request_session
28
-
29
- loop do
30
- send_queued
31
- end
32
- end
33
- end
34
-
35
- def cleanup
36
- @http.finish if @http.started?
37
- end
38
-
39
- private
40
-
41
- def setup_http
42
- @http = Net::HTTP.new(@host, @port)
43
- # TODO: make these configurable somewhere
44
- @http.open_timeout = 1
45
- @http.read_timeout = 1
46
- end
47
-
48
- def request_session
49
- Client.logger.info('making initial request for session...')
50
-
51
- session_req = @http.get(REMOTE_PATHS.fetch(:get_session))
52
-
53
- response = JSON.parse(session_req.body)
54
-
55
- if Integer(session_req.code) != 201
56
- raise "failed to retrieve session: #{response}"
57
- end
58
-
59
- @sid = response['sid']
60
- Client.logger.info("current session id: #{@sid}")
61
- end
62
-
63
- # given the result of a .get or .post, converts the response code,
64
- # and executes the (side effecting) block if the response was not
65
- # successful. calls the block with a message describing the error.
66
- def if_not_ok(http_req, ok_code = 200, &_b)
67
- yield http_req.body if Integer(http_req.code) != ok_code
68
- end
69
-
70
- def send_queued
71
- Client.logger.info("processing message with #{@outgoing.size} messages outgoing")
72
-
73
- message_data = {
74
- from: @sid,
75
- to: '*',
76
- msg: @outgoing.pop
77
- }.to_json
78
-
79
- post_req = @http.post(REMOTE_PATHS.fetch(:post_message), message_data)
80
-
81
- if_not_ok(post_req) do |err|
82
- Client.logger.warn("failed to post message: #{message_data} #{err}")
83
- end
84
- end # send_queued
85
- end # RemoteOutputHandler
86
- end # Handlers
87
- end # Glottis
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+ require 'uri'
5
+ require 'net/http'
6
+ require 'json'
7
+
8
+ module Glottis
9
+ module Handlers
10
+ # Manages posting outgoing messages to the remote valyx server.
11
+ class RemoteOutputHandler
12
+ POLL_INTERVAL = 0.1
13
+ PROTOCOL = 'http'
14
+
15
+ REMOTE_PATHS = {
16
+ get_session: '/api/session',
17
+ post_message: '/api/message'
18
+ }.freeze
19
+
20
+ def initialize(outgoing, host, port)
21
+ @outgoing = outgoing
22
+ @host = host
23
+ @port = port
24
+ @running = false
25
+ @thread = nil
26
+ @sid = nil
27
+ setup_http
28
+ end
29
+
30
+ def start
31
+ @running = true
32
+ @thread = Thread.new do
33
+ @http.start
34
+ request_session
35
+
36
+ send_queued while @running
37
+ end
38
+ self
39
+ end
40
+
41
+ def join
42
+ @thread&.join
43
+ end
44
+
45
+ def cleanup
46
+ @running = false
47
+ @http.finish if @http.started?
48
+ @thread&.kill if @thread&.alive?
49
+ end
50
+
51
+ private
52
+
53
+ def setup_http
54
+ @http = Net::HTTP.new(@host, @port)
55
+ @http.open_timeout = 1
56
+ @http.read_timeout = 1
57
+ end
58
+
59
+ def request_session
60
+ Client.logger.info('making initial request for session...')
61
+
62
+ session_req = @http.get(REMOTE_PATHS.fetch(:get_session))
63
+ response = JSON.parse(session_req.body)
64
+
65
+ raise "failed to retrieve session: #{response}" if Integer(session_req.code) != 201
66
+
67
+ @sid = response['sid']
68
+ Client.logger.info("current session id: #{@sid}")
69
+ end
70
+
71
+ def if_not_ok(http_req, ok_code = 200)
72
+ yield http_req.body if Integer(http_req.code) != ok_code
73
+ end
74
+
75
+ def send_queued
76
+ raw_msg = @outgoing.pop
77
+ return if raw_msg.nil? || raw_msg == :shutdown
78
+
79
+ Client.logger.info("processing message with #{@outgoing.size} messages outgoing")
80
+
81
+ message_data = {
82
+ from: @sid,
83
+ to: '*',
84
+ msg: raw_msg
85
+ }.to_json
86
+
87
+ headers = { 'Content-Type' => 'application/json' }
88
+ post_req = @http.post(REMOTE_PATHS.fetch(:post_message), message_data, headers)
89
+
90
+ if_not_ok(post_req) do |err|
91
+ Client.logger.warn("failed to post message: #{message_data} #{err}")
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Glottis
2
- VERSION = '0.1.3'.freeze
4
+ VERSION = '0.3.1'
3
5
  end
data/lib/glottis.rb CHANGED
@@ -1,2 +1,4 @@
1
- require 'glottis/version'
2
- require 'glottis/client'
1
+ # frozen_string_literal: true
2
+
3
+ require 'glottis/version'
4
+ require 'glottis/client'
metadata CHANGED
@@ -1,86 +1,98 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glottis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max DeLiso
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2016-02-16 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: rb-readline
13
+ name: slop
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: 0.5.3
18
+ version: '4.10'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: 0.5.3
25
+ version: '4.10'
27
26
  - !ruby/object:Gem::Dependency
28
- name: slop
27
+ name: bundler
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '2.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rake
29
42
  requirement: !ruby/object:Gem::Requirement
30
43
  requirements:
31
44
  - - "~>"
32
45
  - !ruby/object:Gem::Version
33
- version: '4.2'
34
- type: :runtime
46
+ version: '13.0'
47
+ type: :development
35
48
  prerelease: false
36
49
  version_requirements: !ruby/object:Gem::Requirement
37
50
  requirements:
38
51
  - - "~>"
39
52
  - !ruby/object:Gem::Version
40
- version: '4.2'
53
+ version: '13.0'
41
54
  - !ruby/object:Gem::Dependency
42
- name: bundler
55
+ name: rspec
43
56
  requirement: !ruby/object:Gem::Requirement
44
57
  requirements:
45
58
  - - "~>"
46
59
  - !ruby/object:Gem::Version
47
- version: '1.10'
60
+ version: '3.0'
48
61
  type: :development
49
62
  prerelease: false
50
63
  version_requirements: !ruby/object:Gem::Requirement
51
64
  requirements:
52
65
  - - "~>"
53
66
  - !ruby/object:Gem::Version
54
- version: '1.10'
67
+ version: '3.0'
55
68
  - !ruby/object:Gem::Dependency
56
- name: rake
69
+ name: rubocop
57
70
  requirement: !ruby/object:Gem::Requirement
58
71
  requirements:
59
72
  - - "~>"
60
73
  - !ruby/object:Gem::Version
61
- version: '10.0'
74
+ version: '1.0'
62
75
  type: :development
63
76
  prerelease: false
64
77
  version_requirements: !ruby/object:Gem::Requirement
65
78
  requirements:
66
79
  - - "~>"
67
80
  - !ruby/object:Gem::Version
68
- version: '10.0'
81
+ version: '1.0'
69
82
  - !ruby/object:Gem::Dependency
70
- name: rubocop
83
+ name: webrick
71
84
  requirement: !ruby/object:Gem::Requirement
72
85
  requirements:
73
86
  - - "~>"
74
87
  - !ruby/object:Gem::Version
75
- version: 0.37.2
88
+ version: '1.8'
76
89
  type: :development
77
90
  prerelease: false
78
91
  version_requirements: !ruby/object:Gem::Requirement
79
92
  requirements:
80
93
  - - "~>"
81
94
  - !ruby/object:Gem::Version
82
- version: 0.37.2
83
- description:
95
+ version: '1.8'
84
96
  email:
85
97
  - maxdeliso@gmail.com
86
98
  executables:
@@ -88,14 +100,9 @@ executables:
88
100
  extensions: []
89
101
  extra_rdoc_files: []
90
102
  files:
91
- - ".gitignore"
92
- - ".rubocop.yml"
93
- - ".travis.yml"
94
- - Gemfile
103
+ - CHANGELOG.md
95
104
  - README.md
96
105
  - Rakefile
97
- - bin/console
98
- - bin/setup
99
106
  - exe/glottis
100
107
  - glottis.gemspec
101
108
  - lib/glottis.rb
@@ -110,8 +117,12 @@ files:
110
117
  homepage: https://github.com/maxdeliso/glottis
111
118
  licenses:
112
119
  - MIT
113
- metadata: {}
114
- post_install_message:
120
+ metadata:
121
+ homepage_uri: https://github.com/maxdeliso/glottis
122
+ source_code_uri: https://github.com/maxdeliso/glottis
123
+ changelog_uri: https://github.com/maxdeliso/glottis/blob/main/CHANGELOG.md
124
+ bug_tracker_uri: https://github.com/maxdeliso/glottis/issues
125
+ rubygems_mfa_required: 'true'
115
126
  rdoc_options: []
116
127
  require_paths:
117
128
  - lib
@@ -119,16 +130,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
119
130
  requirements:
120
131
  - - ">="
121
132
  - !ruby/object:Gem::Version
122
- version: '0'
133
+ version: 3.0.0
123
134
  required_rubygems_version: !ruby/object:Gem::Requirement
124
135
  requirements:
125
136
  - - ">="
126
137
  - !ruby/object:Gem::Version
127
138
  version: '0'
128
139
  requirements: []
129
- rubyforge_project:
130
- rubygems_version: 2.4.5.1
131
- signing_key:
140
+ rubygems_version: 3.6.9
132
141
  specification_version: 4
133
142
  summary: simple http messaging client
134
143
  test_files: []
data/.gitignore DELETED
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- *.log
11
- *.gem
data/.rubocop.yml DELETED
@@ -1,5 +0,0 @@
1
- Metrics/LineLength:
2
- Max: 99
3
-
4
- Metrics/MethodLength:
5
- Max: 20
data/.travis.yml DELETED
@@ -1,4 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.1.5
4
- before_install: gem install bundler -v 1.10.6
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in glottis.gemspec
4
- gemspec
data/bin/console DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'bundler/setup'
4
- require 'glottis'
5
- require 'irb'
6
-
7
- IRB.start
data/bin/setup DELETED
@@ -1,7 +0,0 @@
1
- #!/bin/bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
-
5
- bundle install
6
-
7
- # Do any other automated setup that you need to do here