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 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
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in soa.gemspec
6
+ gemspec
7
+
8
+ gem "pry"
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
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,3 @@
1
+ class SOA
2
+ VERSION = "1.0.0"
3
+ end
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
@@ -0,0 +1,8 @@
1
+ require "soa"
2
+
3
+ service "/api/user/:id" do |id|
4
+ puts "finding user #{id}"
5
+ end
6
+
7
+ call_service "/api/user/45" # => puts "finding user 45"
8
+
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: []