harmony-service 0.2.0 → 0.3.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
  SHA1:
3
- metadata.gz: 89bf205b49b089b6efc12ebdb0e91132b1ae0b27
4
- data.tar.gz: 5b33365abe55dadeeff62276c044d548b545b820
3
+ metadata.gz: 3b38543c27255399b4d62dc894bd21a6b585d73e
4
+ data.tar.gz: b887efe0fd12aebe15f877964bd2d82de5460084
5
5
  SHA512:
6
- metadata.gz: 595e1653de7f3f381e4f99fe5d19659de9e480f166fb31b06c07255b525dddf12536f3fe4778b0434bd1509ea78b7ae10fa3ee5b150a8566cb56539e51cd6d6d
7
- data.tar.gz: cf1b3d953239ac5958afc720778534367426245cce561c8ca0efe4c271770106c90b07a0c51cdb9c9934e011b4ae65ddf626e431ec9d3a1f75c9c126ecb72ff2
6
+ metadata.gz: cbf739554afce68602f12c1bc07e1e2d9c9848ad7f1d19f286d2a645cf6a5486246c4df8bb4b36215991e4215a8e25eadbbfd1c4de2b32ecbf8200e79b4c25cf
7
+ data.tar.gz: 3eafe55ff0d0ffdf6798a6bcda38684338388fe9ef9ceb8374909674aa345028fec3c63097b68c6aa44a0ce54bb115b5102a30cad121d410efded47dfdc2bc1a
data/README.md CHANGED
@@ -1,41 +1,21 @@
1
1
  # Harmony::Service
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/harmony/service`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ The Harmony Service gem simplifies creation of a Service in the Harmony Platform.
6
4
 
7
5
  ## Installation
8
6
 
9
- Add this line to your application's Gemfile:
10
-
11
- ```ruby
12
- gem 'harmony-service'
13
- ```
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install harmony-service
7
+ 1. Create a new Service via the Harmony platform
8
+ 1. Download the code for your Service.
9
+ 1. Run `bundle install`
22
10
 
23
11
  ## Usage
24
12
 
25
- TODO: Write usage instructions here
13
+ In order to test your code locally you can run `bundle exec rspec`. Once you have completed development you can upload into the Harmony Platform.
26
14
 
27
15
  ## Development
28
16
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
-
33
- ## Contributing
34
-
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/harmony-service.
36
-
17
+ Your Service should respond to request messages appropriately. You can find the relevant mappings [here](https://github.com/HarmonyMobile/harmony-service/blob/master/lib/harmony/service/rpc_service.rb#L95).
37
18
 
38
19
  ## License
39
20
 
40
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
-
21
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ require 'sneakers'
3
+ require 'sneakers/runner'
4
+ require 'harmony/service'
5
+
6
+ abort("usage: harmony_service [handler class name] --require [handler class file]") unless ARGV.length == 3
7
+
8
+ handler_class = ARGV[0]
9
+ puts "Starting Harmony Service with handler: #{handler_class}"
10
+ load File.expand_path(ARGV[2])
11
+
12
+ opts = {
13
+ amqp: ENV['ampq_address'] || 'amqp://localhost:5672',
14
+ vhost: ENV['ampq_vhost'] || '/',
15
+ exchange: 'sneakers',
16
+ exchange_type: :direct,
17
+ metrics: Sneakers::Metrics::LoggingMetrics.new,
18
+ handler: Sneakers::Handlers::Maxretry,
19
+ handler_class: handler_class
20
+ }
21
+
22
+ Sneakers.server = true
23
+ Sneakers.configure(opts)
24
+ Sneakers.logger.level = ENV['log_level'] == 'debug' ? Logger::DEBUG : Logger::INFO
25
+
26
+ Rollbar.configure do |config|
27
+ config.access_token = ENV['rollbar_access_token']
28
+ config.environment = ENV['RACK_ENV']
29
+ config.enabled = ENV['RACK_ENV'] == 'staging' || ENV['RACK_ENV'] == 'production'
30
+ end
31
+
32
+ r = Sneakers::Runner.new([Harmony::Service::RpcService])
33
+ pid = Sneakers::CONFIG[:pid_path]
34
+ puts "Started pid: #{pid}"
35
+ r.run
@@ -11,9 +11,9 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = "Gem which helps you to build Harmony services"
12
12
  spec.homepage = "https://github.com/HarmonyMobile/harmony-service"
13
13
  spec.license = "MIT"
14
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
- spec.bindir = "exe"
16
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
14
+ spec.files = `git ls-files`.split($/).reject { |f| f == 'Gemfile.lock' }
15
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
16
+ spec.executables = spec.files.grep(/^bin/).map { |f| File.basename(f) }
17
17
  spec.require_paths = ["lib"]
18
18
 
19
19
  spec.add_dependency "sneakers", '~> 2.4'
@@ -1,3 +1,3 @@
1
1
  class Harmony::Service::Calculator::Request < Harmony::Service::Request
2
- attr_accessor :inputs
2
+ attr_accessor :uri, :inputs, :outputs
3
3
  end
@@ -0,0 +1,3 @@
1
+ class Harmony::Service::Flow::EndedRequest < Harmony::Service::Request
2
+ attr_accessor :pages
3
+ end
@@ -0,0 +1,3 @@
1
+ class Harmony::Service::Form::GetRequest < Harmony::Service::Request
2
+ attr_accessor :inputs
3
+ end
@@ -0,0 +1,3 @@
1
+ class Harmony::Service::Form::GetResponse < Harmony::Service::Request
2
+ attr_accessor :input_values
3
+ end
@@ -5,29 +5,11 @@ require 'json'
5
5
  require 'oj'
6
6
  require 'rollbar'
7
7
 
8
- opts = {
9
- amqp: ENV['ampq_address'] || 'amqp://localhost:5672',
10
- vhost: ENV['ampq_vhost'] || '/',
11
- exchange: 'sneakers',
12
- exchange_type: :direct,
13
- metrics: Sneakers::Metrics::LoggingMetrics.new,
14
- handler: Sneakers::Handlers::Maxretry
15
- }
16
-
17
- Sneakers.configure(opts)
18
- Sneakers.logger.level = ENV['log_level'] == 'debug' ? Logger::DEBUG : Logger::INFO
19
-
20
- Rollbar.configure do |config|
21
- config.access_token = ENV['rollbar_access_token']
22
- config.environment = ENV['RACK_ENV']
23
- config.enabled = ENV['RACK_ENV'] == 'staging' || ENV['RACK_ENV'] == 'production'
24
- end
25
-
26
8
  module Harmony
27
9
  module Service
28
10
  class RpcService
29
-
30
11
  include Sneakers::Worker
12
+ from_queue ENV['harmony_queue'], timeout_job_after: 10, threads: 1
31
13
 
32
14
  def work_with_params(message, delivery_info, metadata)
33
15
  begin
@@ -35,9 +17,9 @@ module Harmony
35
17
  request = Oj.load(message)
36
18
  request_class = request.class
37
19
  response_class = request_response_mapping[request_class]
38
- raise "Unacceptable request class: #{request_class}" if response_class.nil?
20
+ raise "Unacceptable request class: #{request_class}" if response_class.nil?
39
21
 
40
- result = work_with_request(request)
22
+ result = new_handler.work_with_request(request)
41
23
  raise "Unacceptable response class: #{result.class}" unless response_class === result
42
24
 
43
25
  json = Oj.dump(result)
@@ -98,9 +80,19 @@ module Harmony
98
80
  ActionList::ListRequest => Array,
99
81
  ActionList::ItemRequest => ActionList::Item,
100
82
  ActionList::ActionRequest => NilClass,
101
- Chart::Request => Chart::Response
83
+ Chart::Request => Chart::Response,
84
+ Form::GetRequest => Form::GetResponse,
85
+ Flow::EndedRequest => Response
102
86
  }
103
87
  end
88
+
89
+ def new_handler
90
+ handler_class = Sneakers::CONFIG[:handler_class]
91
+ raise "No handler specified" if handler_class.nil?
92
+
93
+ handler = Object.const_get(handler_class).new
94
+ raise "Unable to create handler: #{handler_class}" if handler.nil?
95
+ end
104
96
  end
105
97
  end
106
98
  end
@@ -1,6 +1,6 @@
1
1
  module Harmony
2
2
  module Service
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
6
6
 
@@ -16,3 +16,11 @@ end
16
16
  module Harmony::Service::ActionList
17
17
 
18
18
  end
19
+
20
+ module Harmony::Service::Form
21
+
22
+ end
23
+
24
+ module Harmony::Service::Flow
25
+
26
+ end
@@ -16,5 +16,10 @@ require 'harmony/service/action_list/list_request'
16
16
  require 'harmony/service/action_list/item_request'
17
17
  require 'harmony/service/action_list/item'
18
18
 
19
+ require 'harmony/service/form/get_request'
20
+ require 'harmony/service/form/get_response'
21
+
22
+ require 'harmony/service/flow/ended_request'
23
+
19
24
  require "harmony/service/rpc_service"
20
25
 
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harmony::Service::RpcService do
4
+
5
+ describe "#work_with_params" do
6
+ let(:metadata) { instance_double("Metadata", reply_to: "harmony.trello", correlation_id: "abc123") }
7
+ let(:handler) { handler = double("Object") }
8
+
9
+ context "ack!" do
10
+ before(:each) do
11
+ expect(handler).to receive(:work_with_request).with(kind_of(request.class)) { response }
12
+ allow(subject).to receive(:new_handler) { handler }
13
+ allow(subject).to receive(:send_response)
14
+ allow(subject).to receive(:ack!)
15
+ subject.work_with_params(Oj.dump(request), {}, metadata)
16
+ end
17
+
18
+ context "calculation" do
19
+ let(:request) { Harmony::Service::Calculator::Request.new(harmony_user_email: "matt@futureworkshops.com", inputs: {"lat" => "51.0", "lon" => "0.1"}) }
20
+ let(:response) { Harmony::Service::Calculator::Response.new(outputs: {price: 50})}
21
+
22
+ it { expect(subject).to have_received(:send_response).with("{\"^o\":\"Harmony::Service::Calculator::Response\",\"outputs\":{\":price\":50}}", "harmony.trello", "abc123") }
23
+ it { expect(subject).to have_received(:ack!) }
24
+ end
25
+
26
+ context "action list" do
27
+ context "list" do
28
+ let(:request) { Harmony::Service::ActionList::ListRequest.new(harmony_user_email: "matt@futureworkshops.com", page: 0, per_page: 10) }
29
+ let(:response) { [Harmony::Service::ActionList::Item.new({id: 1, title: "Carrots"})]}
30
+
31
+ it { expect(subject).to have_received(:send_response).with("[{\"^o\":\"Harmony::Service::ActionList::Item\",\"id\":1,\"title\":\"Carrots\"}]", "harmony.trello", "abc123") }
32
+ it { expect(subject).to have_received(:ack!) }
33
+ end
34
+
35
+ context "item" do
36
+ let(:request) { Harmony::Service::ActionList::ItemRequest.new(harmony_user_email: "matt@futureworkshops.com", id: 1) }
37
+ let(:response) { Harmony::Service::ActionList::Item.new({id: 1, title: "Carrots", subtitle: "Bag of Carrots", detail_html: "<html><body>Carrots</body></html>"})}
38
+
39
+ it { expect(subject).to have_received(:send_response).with("{\"^o\":\"Harmony::Service::ActionList::Item\",\"id\":1,\"title\":\"Carrots\",\"subtitle\":\"Bag of Carrots\",\"detail_html\":\"<html><body>Carrots</body></html>\"}", "harmony.trello", "abc123") }
40
+ it { expect(subject).to have_received(:ack!) }
41
+ end
42
+
43
+ context "action" do
44
+ let(:request) { Harmony::Service::ActionList::ActionRequest.new(harmony_user_email: "matt@futureworkshops.com", id: 1, action: "Done") }
45
+ let(:response) { nil }
46
+
47
+ it { expect(subject).to have_received(:send_response).with("null", "harmony.trello", "abc123") }
48
+ it { expect(subject).to have_received(:ack!) }
49
+ end
50
+ end
51
+
52
+ context "chart" do
53
+ let(:request) { Harmony::Service::Chart::Request.new(harmony_user_email: "matt@futureworkshops.com") }
54
+ let(:response) { Harmony::Service::Chart::Response.new(x_values: ["Jan", "Feb", "Mar"], y_values: [10, 20, 40])}
55
+ it { expect(subject).to have_received(:send_response).with("{\"^o\":\"Harmony::Service::Chart::Response\",\"x_values\":[\"Jan\",\"Feb\",\"Mar\"],\"y_values\":[10,20,40]}", "harmony.trello", "abc123") }
56
+ it { expect(subject).to have_received(:ack!) }
57
+ end
58
+
59
+ context "form" do
60
+ context 'get' do
61
+ let(:request) { Harmony::Service::Form::GetRequest.new(harmony_user_email: "matt@futureworkshops.com", inputs: ['satisfaction_level']) }
62
+ let(:response) { Harmony::Service::Form::GetResponse.new({input_values: [{'satisfaction_level': ['1','2','3']}]})}
63
+ it { expect(subject).to have_received(:send_response).with("{\"^o\":\"Harmony::Service::Form::GetResponse\",\"input_values\":[{\":satisfaction_level\":[\"1\",\"2\",\"3\"]}],\"options\":{}}", "harmony.trello", "abc123") }
64
+ it { expect(subject).to have_received(:ack!) }
65
+ end
66
+ end
67
+
68
+ context "flow ended" do
69
+ let(:request) { Harmony::Service::Flow::EndedRequest.new(harmony_user_email: "matt@futureworkshops.com", pages: [{page_id: 1}]) }
70
+ let(:response) { Harmony::Service::Response.new}
71
+ it { expect(subject).to have_received(:send_response).with("{\"^o\":\"Harmony::Service::Response\"}", "harmony.trello", "abc123") }
72
+ it { expect(subject).to have_received(:ack!) }
73
+ end
74
+
75
+ end
76
+
77
+ context "unacceptable request class" do
78
+ before(:each) do
79
+ allow(subject).to receive(:work_with_request).and_raise("A timeout occured")
80
+ allow(subject).to receive(:send_response)
81
+ allow(subject).to receive(:reject!)
82
+
83
+ metadata = instance_double("Metadata", reply_to: "harmony.trello", correlation_id: "abc123")
84
+ subject.work_with_params("{\"trello_board_id\": \"12345\"}", {}, metadata)
85
+ end
86
+
87
+ it { expect(subject).to have_received(:send_response).with("{\"^o\":\"Harmony::Service::ErrorResponse\",\"message\":\"An error occured.\",\"detailed_message\":\"Unacceptable request class: Hash\"}", "harmony.trello", "abc123") }
88
+ it { expect(subject).to have_received(:reject!) }
89
+ end
90
+ end
91
+
92
+
93
+ end
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'harmony/service'
3
+ require 'byebug'
4
+
5
+ opts = {
6
+ amqp: 'amqp://localhost:5672',
7
+ vhost: '/',
8
+ exchange: 'sneakers',
9
+ exchange_type: :direct,
10
+ metrics: Sneakers::Metrics::LoggingMetrics.new,
11
+ handler: Sneakers::Handlers::Maxretry
12
+ }
13
+
14
+ Sneakers.configure(opts)
15
+ Sneakers.logger.level = Logger::DEBUG
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: harmony-service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Brooke-Smith
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-24 00:00:00.000000000 Z
11
+ date: 2017-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sneakers
@@ -111,7 +111,8 @@ dependencies:
111
111
  description:
112
112
  email:
113
113
  - matt@futureworkshops.com
114
- executables: []
114
+ executables:
115
+ - harmony_service
115
116
  extensions: []
116
117
  extra_rdoc_files: []
117
118
  files:
@@ -124,8 +125,7 @@ files:
124
125
  - LICENSE.txt
125
126
  - README.md
126
127
  - Rakefile
127
- - bin/console
128
- - bin/setup
128
+ - bin/harmony_service
129
129
  - harmony-service.gemspec
130
130
  - lib/harmony/service.rb
131
131
  - lib/harmony/service/action_list/action_request.rb
@@ -137,11 +137,16 @@ files:
137
137
  - lib/harmony/service/chart/request.rb
138
138
  - lib/harmony/service/chart/response.rb
139
139
  - lib/harmony/service/error_response.rb
140
+ - lib/harmony/service/flow/ended_request.rb
141
+ - lib/harmony/service/form/get_request.rb
142
+ - lib/harmony/service/form/get_response.rb
140
143
  - lib/harmony/service/message.rb
141
144
  - lib/harmony/service/request.rb
142
145
  - lib/harmony/service/response.rb
143
146
  - lib/harmony/service/rpc_service.rb
144
147
  - lib/harmony/service/version.rb
148
+ - spec/harmony/rpc_service_spec.rb
149
+ - spec/spec_helper.rb
145
150
  homepage: https://github.com/HarmonyMobile/harmony-service
146
151
  licenses:
147
152
  - MIT
@@ -166,4 +171,6 @@ rubygems_version: 2.4.5.1
166
171
  signing_key:
167
172
  specification_version: 4
168
173
  summary: Gem which helps you to build Harmony services
169
- test_files: []
174
+ test_files:
175
+ - spec/harmony/rpc_service_spec.rb
176
+ - spec/spec_helper.rb
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "harmony/service"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- 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