SMService 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba77f89b36377c88a36275cae2ee1cb0fe7933070fe29ee26dc52afcd5d3be14
4
- data.tar.gz: cf59fc3d4f92594b23817a59c4e5623d3e2ba75898894fd7f8aa52402d0fc22a
3
+ metadata.gz: b23b4edc0d637c75e9dbdb47cfcbb141e541d0d74411188613e32d7765005559
4
+ data.tar.gz: c59f2fefb1f552fa7cf43cdd225aa61a00478464468de80d03a17f3a72a4b146
5
5
  SHA512:
6
- metadata.gz: 9c57d922c113e68c45b4dc068e771795c4e1782b8701b1492513b55b662ac51eb73871c35cb90b27aeb911337b968d29877527894427007fdf23b6e67f76f574
7
- data.tar.gz: 0b8dc1990f4e49fb3937d7da8ab818bc71f15d9e945b625617593d39bef173398d3460c88b45928914962e3f9da02a3cb9473039a53d3352547ee0914607b838
6
+ metadata.gz: f2dd0714308ff1120b302e376f6cd963b85aea0c129ff98a5d669866ac7ebb281a1390d7c89d137504b6591b3589ba14439900d6f9e7002b27085e50f45eca48
7
+ data.tar.gz: dbbe8b2b31c9a843ec235d679ecaddcaf0f91093747e1af8addec9f62574674ac18335b64d19492080146082da9bf1ddc9bebf61bac0ce7b5c625d4a8e10c813
data/Dockerfile CHANGED
@@ -20,8 +20,9 @@ RUN apk update \
20
20
  pcre \
21
21
  zlib \
22
22
  tzdata \
23
- mc \
23
+ tmux \
24
24
  vim \
25
+ mc \
25
26
  \
26
27
  && cp -R /usr/share/zoneinfo/Europe/Amsterdam /etc/localtime \
27
28
  && echo 'Europe/Amsterdam' > /etc/timezone \
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- SMService (0.1.3)
4
+ SMService (0.1.5)
5
5
  ffi-rzmq (~> 2.0)
6
6
  logger (~> 1.2)
7
7
  msgpack (~> 1.1)
@@ -9,6 +9,7 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
+ coderay (1.1.2)
12
13
  diff-lcs (1.3)
13
14
  ffi (1.9.18)
14
15
  ffi-rzmq (2.0.5)
@@ -16,7 +17,11 @@ GEM
16
17
  ffi-rzmq-core (1.0.6)
17
18
  ffi
18
19
  logger (1.2.8)
20
+ method_source (0.9.0)
19
21
  msgpack (1.1.0)
22
+ pry (0.11.3)
23
+ coderay (~> 1.1.0)
24
+ method_source (~> 0.9.0)
20
25
  rake (10.5.0)
21
26
  rspec (3.7.0)
22
27
  rspec-core (~> 3.7.0)
@@ -38,6 +43,7 @@ PLATFORMS
38
43
  DEPENDENCIES
39
44
  SMService!
40
45
  bundler (~> 1.16)
46
+ pry (~> 0.11)
41
47
  rake (~> 10.0)
42
48
  rspec (~> 3.0)
43
49
 
@@ -36,6 +36,7 @@ Gem::Specification.new do |s|
36
36
 
37
37
 
38
38
  s.add_development_dependency "bundler", "~> 1.16"
39
+ s.add_development_dependency "pry", "~> 0.11"
39
40
  s.add_development_dependency "rake", "~> 10.0"
40
41
  s.add_development_dependency "rspec", "~> 3.0"
41
42
  end
@@ -1,16 +1,30 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'rubygems'
4
+ require 'pry'
3
5
  require 'bundler'
4
6
  Bundler.setup
5
7
  Bundler.require
6
8
  require 'smservice'
9
+ require_relative '../examples/dummy'
7
10
 
8
- # You can add fixtures and/or initialization code here to make experimenting
9
- # with your gem easier. You can also use a different console, if you like.
11
+ class SMService::Test
12
+ include SMService
10
13
 
11
- # (If you use this, don't forget to add pry to your Gemfile!)
12
- # require "pry"
13
- # Pry.start
14
+ def initialize
15
+ super name: 'test_ruby', actions: 'test'
16
+ end
14
17
 
15
- require "irb"
16
- IRB.start(__FILE__)
18
+ def action_test(headers, message)
19
+ LOGGER.info "#{self.class} - Processing action 'test'. Headers: #{headers.inspect}, message: #{message.inspect}"
20
+ end
21
+ end
22
+
23
+ dummy = SMService::Dummy.new
24
+ dummy.start!
25
+
26
+ test = SMService::Test.new
27
+ test.start!
28
+
29
+ # dummy.execute(action: 'test', message: {my_request: 'ping', my_data: 'add whatever data needed'})
30
+ binding.pry
@@ -0,0 +1,15 @@
1
+ version: '3'
2
+
3
+ networks:
4
+ middleware:
5
+ external:
6
+ name: middleware_default
7
+
8
+ services:
9
+ rubygems:
10
+ build: .
11
+ container_name: rubygems
12
+ volumes:
13
+ - ./:/app
14
+ networks:
15
+ - middleware
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+
3
+ docker build --pull -t rubygems . && \
4
+ docker run -ti --rm --name=rubygems -v ${PWD}:/app rubygems sh
@@ -0,0 +1,11 @@
1
+ class SMService::Dummy
2
+ include SMService
3
+
4
+ def initialize
5
+ super name: 'dummy_ruby', actions: 'someaction'
6
+ end
7
+
8
+ def action_someaction(headers, message)
9
+ LOGGER.info("Processing action 'someaction'. Headers: #{headers.inspect}, message: #{message.inspect}")
10
+ end
11
+ end
@@ -5,19 +5,42 @@ require 'ffi-rzmq'
5
5
  require 'smservice/version'
6
6
 
7
7
  module SMService
8
+ Thread.abort_on_exception = true
9
+
8
10
  LOGGER = Logger.new(STDERR)
9
11
 
10
12
  ENDPOINT_OUT = 'tcp://proxy:6660'
11
13
  ENDPOINT_IN = 'tcp://proxy:6661'
12
14
 
13
- REGISTER_WAIT_TIME = 'infinite'
15
+ REGISTER_WAIT_TIME = 'infinite'
16
+ REGISTER_RETRY = 10
14
17
  KEEPALIVE_WAIT_TIME = 30
15
18
 
16
19
  attr_accessor :socket_in, :socket_out
17
20
  attr_reader :service_name
18
21
 
19
- def initialize(name:)
22
+ # When registering node, following parameters is mandatory:
23
+ #
24
+ # name: name of service/node with its id;
25
+ # actions: list of actions, should be in lowercase and compatible to naming standard for ruby methods
26
+ # actions could be presented as array or as string if service registering only single action
27
+ #
28
+ # Example:
29
+ # SMService::SomeService.new(name: 'dummy-ruby', actions: %w(a b c ping pong))
30
+ #
31
+ # Following actions should be defined as methods for new service, i.e.
32
+ #
33
+ # def action_ping(headers, message)
34
+ # LOGGER.info "#{self.class} - Processing action: PING with headers: #{headers.inspect} and message: #{message.inspect}"
35
+ # # ... business logic here
36
+ # end
37
+ #
38
+ # Prohibited names for actions is register and update, those are reserved to let service communicate with SM.
39
+ # Check SMService::Dummy source code (in examples folder) for detais
40
+ #
41
+ def initialize(name:, actions: [])
20
42
  @service_name = name
43
+ @actions = [%w(ping), actions].flatten.sort.uniq
21
44
 
22
45
  context = ZMQ::Context.new
23
46
  @socket_in = context.socket ZMQ::DEALER
@@ -30,21 +53,41 @@ module SMService
30
53
  @socket_out.connect ENDPOINT_OUT
31
54
  end
32
55
 
33
- def register!(wait_time: REGISTER_WAIT_TIME)
56
+ # starting infinite loop in order to process service logic.
57
+ # start! or service_poller methods could be modified implementing different services, i.e. to run as threaded metod
58
+ def start!
59
+ register
60
+ keep_alive!
61
+ poller!
62
+ end
63
+
64
+ def poller!
65
+ Thread.start do
66
+ poller
67
+ end
68
+ end
69
+
70
+ def poller
71
+ loop do
72
+ pull
73
+ end
74
+ end
75
+
76
+ def register(wait_time: REGISTER_WAIT_TIME)
34
77
  if wait_time.to_f <= 0
35
78
  loop do
36
- register!
79
+ register_service
37
80
  break if registered?
38
81
  # not registered, retrying in 10 seconds
39
- sleep 10
82
+ sleep REGISTER_RETRY
40
83
  end
41
84
  else
42
85
  Timeout::timeout(wait_time) do
43
86
  loop do
44
- register!
87
+ register_service
45
88
  break if registered?
46
89
  # not registered, retrying in 10 seconds
47
- sleep 10
90
+ sleep REGISTER_RETRY
48
91
  end
49
92
  end
50
93
  end
@@ -52,11 +95,11 @@ module SMService
52
95
 
53
96
  def keep_alive!(wait_time: KEEPALIVE_WAIT_TIME)
54
97
  Thread.start do
55
- LOGGER.info "Starting registration update loop with periodic interval #{wait_time} sec"
98
+ LOGGER.info "#{self.class} - Starting registration update loop with periodic interval #{wait_time} sec"
56
99
  loop do
57
100
  break unless registered?
58
101
  sleep wait_time
59
- service_manager('UPDATE', [])
102
+ request(action: 'UPDATE')
60
103
  end
61
104
  LOGGER.info 'Registration update loop terminated'
62
105
  end
@@ -66,55 +109,57 @@ module SMService
66
109
  @registered
67
110
  end
68
111
 
69
- def register!
70
- service_manager('REGISTER', services: [service_name])
71
- pull_action
72
- end
73
-
74
- def service_poller
75
- loop do
76
- pull_action
77
- end
112
+ def action_register(headers, message)
113
+ if headers['action'] == 'REGISTER' && message['result'] == 'OK'
114
+ @registered = true
115
+ LOGGER.info "#{self.class} - Action: REGISTER (successful), headers: #{headers.inspect}, message: #{message.inspect}"
116
+ else
117
+ LOGGER.info "#{self.class} - Action: REGISTER (failure), headers: #{headers.inspect}, message: #{message.inspect}"
118
+ end
78
119
  end
79
120
 
80
- def start!
81
- register!
82
- keep_alive!
83
- service_poller
121
+ def action_ping(headers, message)
122
+ LOGGER.info "#{self.class} - Processing action 'ping'. Headers: #{headers.inspect}, message: #{message.inspect}"
84
123
  end
85
124
 
86
125
  def action_update(headers, message)
87
- LOGGER.info("Action: UPDATE (successful)")
126
+ LOGGER.info "#{self.class} - Processing action 'update'. Headers: #{headers.inspect}, message: #{message.inspect}"
88
127
  end
89
128
 
90
- def action_register(headers, message)
91
- if headers['action'] == 'REGISTER' && message['result'] == 'OK'
92
- @registered = true
93
- LOGGER.info "Action: REGISTER (successful), headers: #{headers.inspect}, message: #{message.inspect}"
94
- else
95
- LOGGER.info "Action: REGISTER (failure), headers: #{headers.inspect}, message: #{message.inspect}"
96
- end
129
+ # Requesting another service, registered at SM to execute given action, example:
130
+ # execute(action: 'create_customer_portal', message: {my_request: 'should create a customer', my_data: 'add whatever data needed'})
131
+ #
132
+ def execute(action:, message: nil)
133
+ LOGGER.info "#{self.class} - SM execute request. Action: #{action.inspect}, message: #{message.inspect}"
134
+ action = {service: action, reply_to: @service_name}.to_msgpack
135
+ message = message.to_msgpack
136
+ @socket_out.send_strings [action, message]
97
137
  end
98
138
 
99
139
  private
100
140
 
141
+ def register_service
142
+ LOGGER.info "#{self.class} - Registering service #{service_name}"
143
+ request(action: 'REGISTER', message: {services: @actions})
144
+ pull
145
+ end
146
+
101
147
  # Sending request to the Service Manager
102
- #
103
- def service_manager(action, message)
104
- LOGGER.info "SM request. Action: #{action.inspect}, message: #{message.inspect}"
148
+ def request(action:, message: nil)
149
+ LOGGER.info "#{self.class} - SM request. Action: #{action.inspect}, message: #{message.inspect}"
105
150
  action = {action: action}.to_msgpack
106
151
  message = message.to_msgpack
107
152
  @socket_in.send_strings [action, message]
108
153
  end
109
154
 
110
- def pull_action
155
+ def pull
111
156
  @socket_in.recv_strings( response = [] )
112
157
 
113
158
  headers, message = response
114
159
  headers = MessagePack.unpack(headers)
115
160
  message = MessagePack.unpack(message)
116
161
 
117
- LOGGER.info "SM response received by pull_action. Headers: #{headers.inspect}, message: #{message.inspect}"
162
+ LOGGER.info "#{self.class} - SM response received by pull. Headers: #{headers.inspect}, message: #{message.inspect}"
118
163
 
119
164
  # Validates is action_name exists as class method and calling it.
120
165
  # In case, if Service Manager return headers['action'] == 'METHOD_NAME',
@@ -128,17 +173,11 @@ private
128
173
  # - action_register, that confirms registration of node with Service Manager, and
129
174
  # - action_update, that confirms successfule registration update, we need it to support keep-alive
130
175
  #
131
- action_name = "action_#{headers['action'].downcase}".to_sym
176
+ action_name = "action_#{(headers['action'] || headers['service']).downcase}".to_sym
132
177
  if respond_to? action_name.to_sym
133
178
  send(action_name, headers, message)
179
+ else
180
+ LOGGER.error "#{self.class} - Method #{action_name} does not exist in class instance for action name #{headers['action']}"
134
181
  end
135
182
  end
136
183
  end
137
-
138
- class SMService::Dummy
139
- include SMService
140
-
141
- def initialize
142
- super name: 'dummy-ruby'
143
- end
144
- end
@@ -1,3 +1,3 @@
1
1
  module SMService
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.5'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: SMService
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrius Kairiukstis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-17 00:00:00.000000000 Z
11
+ date: 2017-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logger
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.16'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.11'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.11'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -112,11 +126,14 @@ files:
112
126
  - LICENSE.txt
113
127
  - README.md
114
128
  - Rakefile
129
+ - SMService.gemspec
115
130
  - bin/console
116
131
  - bin/setup
132
+ - docker-compose.yml
133
+ - docker.sh
134
+ - examples/dummy.rb
117
135
  - lib/smservice.rb
118
136
  - lib/smservice/version.rb
119
- - smservice.gemspec
120
137
  homepage: https://github.com/andrius/smservice
121
138
  licenses:
122
139
  - MIT