soa 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 +7 -0
- data/.gitignore +8 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +26 -0
- data/README.md +77 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/soa/version.rb +3 -0
- data/lib/soa.rb +50 -0
- data/soa.gemspec +26 -0
- data/test.rb +8 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ffacb34e53562c873c007709b598e657b61b4a496de67275e710eaad794bcc3e
|
4
|
+
data.tar.gz: a06e86233a87f78175a05725edb444dee9cff6d99f72b95a5d280d91f0ab70ce
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f1c64c554ff114962f0bb32af99f02e4b8815752b0d5465ba4f25f84e314413e39f62674724bb4fe6e07d1c6377c52f0c93cac857e48362c668fd014147cf22a
|
7
|
+
data.tar.gz: e38c3c9a7f7047b3b7e1317a8dd3f4e2541edc8989b4d29c63460fd77f6e2ad4458f1b55ac31d8f0126bcd875ac85e62cfb8f09ba857fa4065292a7c4fa6062a
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
soa (1.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
coderay (1.1.2)
|
10
|
+
method_source (0.9.0)
|
11
|
+
pry (0.11.3)
|
12
|
+
coderay (~> 1.1.0)
|
13
|
+
method_source (~> 0.9.0)
|
14
|
+
rake (10.5.0)
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
ruby
|
18
|
+
|
19
|
+
DEPENDENCIES
|
20
|
+
bundler (~> 1.16)
|
21
|
+
pry
|
22
|
+
rake (~> 10.0)
|
23
|
+
soa!
|
24
|
+
|
25
|
+
BUNDLED WITH
|
26
|
+
1.16.3
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# SOA
|
2
|
+
|
3
|
+
A lot of Ruby and Rails developers can see writing on walls that tells them
|
4
|
+
small, focused services are the future. Here is a quote from a well-known
|
5
|
+
Ruby thoughtleader, promoting them on the popular microservice platform
|
6
|
+
called Twitter dot com:
|
7
|
+
|
8
|
+
> Microservices are great for turning method calls in to distributed computing
|
9
|
+
> problems
|
10
|
+
- [Aaron Patterson](https://twitter.com/tenderlove) on [Aug. 9,
|
11
|
+
2018](https://twitter.com/tenderlove/status/1027591532847816704)
|
12
|
+
|
13
|
+
I've helped teams maintain old, slow, and confusing monolithic applications and
|
14
|
+
it's taught me one thing: monolithic codebases become more complex over
|
15
|
+
time. As a result, many companies have decided to build non-monolithic
|
16
|
+
applications instead (these are called "services"; the better, more modern ones
|
17
|
+
are called "microservices"). Applications built with services are initially
|
18
|
+
much more difficult to create and operate, but they also tend to die sooner,
|
19
|
+
which is the best known way to reduce code complexity.
|
20
|
+
|
21
|
+
But how do you write services and microservices in a monolithic language like
|
22
|
+
Ruby? Up until now, writing services required JavaScript and AWS Lambda. But
|
23
|
+
because I prefer to write Ruby and sometimes I work offline (AWS can't be
|
24
|
+
used offline yet), I wrote the SOA gem.
|
25
|
+
|
26
|
+
The SOA gem is a drop-in replacement for Ruby's built-in method dispatch system.
|
27
|
+
You can continue to call legacy methods like you always have alongside new
|
28
|
+
service invocations registered with the SOA gem. It's the perfect companion for
|
29
|
+
teams looking to make a more gradual transition to a services architecture
|
30
|
+
without rewriting their entire years-old system in JavaScript and AWS Lambda.
|
31
|
+
|
32
|
+
## Installation
|
33
|
+
|
34
|
+
To install SOA, we use the command line command `gem` which communicates with
|
35
|
+
the RubyGems.org microservice to download the necessary files:
|
36
|
+
|
37
|
+
```
|
38
|
+
gem install soa
|
39
|
+
```
|
40
|
+
|
41
|
+
And then, in your code, you can activate "SOA mode" in your Ruby interpreter
|
42
|
+
like this
|
43
|
+
|
44
|
+
``` ruby
|
45
|
+
require "soa"
|
46
|
+
```
|
47
|
+
|
48
|
+
[Note that the SOA gem is only tested with C-Ruby. If you want to write services
|
49
|
+
with JRuby, you'll need to wait for the release of a SOAP gem.]
|
50
|
+
|
51
|
+
Once required, the SOA gem will prepare your Ruby runtime to run services and
|
52
|
+
yes microservices instead using our easy-to-use DSL.
|
53
|
+
|
54
|
+
## Usage
|
55
|
+
|
56
|
+
To create a new microservice, we use the `service` method and specify a route
|
57
|
+
path like so:
|
58
|
+
|
59
|
+
``` ruby
|
60
|
+
require "soa"
|
61
|
+
|
62
|
+
service "/api/user/:id" do |id|
|
63
|
+
User.find(id)
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
In order to invoke a SOA microservice, we just `call_service` with the URL. The
|
68
|
+
service is then looked up from the SOA Service Registry, the params are parsed,
|
69
|
+
the service is invoked, and the results are returned.
|
70
|
+
|
71
|
+
``` ruby
|
72
|
+
user = call_service "/api/user/45"
|
73
|
+
puts user.id # => 45
|
74
|
+
```
|
75
|
+
|
76
|
+
It would barely be any easier to just define and call a legacy monolithic Ruby
|
77
|
+
method!
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "soa"
|
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(__FILE__)
|
data/bin/setup
ADDED
data/lib/soa/version.rb
ADDED
data/lib/soa.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require "soa/version"
|
2
|
+
|
3
|
+
class SOA
|
4
|
+
ServiceCall = Struct.new(:route, :service, :args)
|
5
|
+
|
6
|
+
def self.register(route, blk)
|
7
|
+
@services ||= {}
|
8
|
+
@services[route] = blk
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.invoke(url)
|
12
|
+
service_call = service_lookup(url)
|
13
|
+
service_call.service.call(*service_call.args)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def self.service_lookup(url)
|
19
|
+
route, service = @services.find { |(route, _)|
|
20
|
+
parse_params(route, url).all? { |(route_component, url_component)|
|
21
|
+
route_component == url_component || route_component.start_with?(":")
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
return ServiceCall.new(route, service, parse_args(route, url))
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.parse_params(route, url)
|
29
|
+
route.split("/").zip(url.split("/"))
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.parse_args(route, url)
|
33
|
+
parse_params(route, url).select { |(route_component, _)|
|
34
|
+
route_component.start_with?(":")
|
35
|
+
}.map { |(_, url_component)|
|
36
|
+
url_component
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
module Kernel
|
43
|
+
def service(route, &blk)
|
44
|
+
Soa.register(route, blk)
|
45
|
+
end
|
46
|
+
|
47
|
+
def call_service(url, *args)
|
48
|
+
Soa.invoke(url, *args)
|
49
|
+
end
|
50
|
+
end
|
data/soa.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "soa/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "soa"
|
8
|
+
spec.version = SOA::VERSION
|
9
|
+
spec.authors = ["Justin Searls"]
|
10
|
+
spec.email = ["searls@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Helps you migrate from monolithic Ruby to services}
|
13
|
+
spec.homepage = "https://github.com/searls/soa"
|
14
|
+
|
15
|
+
# Specify which files should be added to the gem when it is released.
|
16
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
17
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
18
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
end
|
data/test.rb
ADDED
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: soa
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Searls
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- searls@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- Gemfile.lock
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- bin/console
|
54
|
+
- bin/setup
|
55
|
+
- lib/soa.rb
|
56
|
+
- lib/soa/version.rb
|
57
|
+
- soa.gemspec
|
58
|
+
- test.rb
|
59
|
+
homepage: https://github.com/searls/soa
|
60
|
+
licenses: []
|
61
|
+
metadata: {}
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 2.7.6
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: Helps you migrate from monolithic Ruby to services
|
82
|
+
test_files: []
|