StartHer
This gem provides the basic components required for each application involved in a microservice architecture.
It is based on Redis PubSub (slighlty improved).
Microservices components:
- Publish message to a channel (with reliable support)
- Subscribe to a channel
- Automatic connection retry for Publish and Subscribe
- Comes with a logger, Logstash, which can be re-used in the parent project
- Microservices version discovery:
When starting the subscriber it subscribes to channel hb_ping
(by default).
If it receives a request
(ie a ping request) it replies on channel hb_pong
with the following data (by default):
- service name
- version
- microservice id (hostname,... not defined yet)
- original
request
Requirements
- Ruby >= 2.2
- Redis >= 2.8
Installation
gem 'start_her'
Configuration
require 'start_her'
StartHer.configure do |config|
config.redis = {
url: 'redis://localhost:6379',
namespace: 'namespace'
db: 1
}
config.logger = StartHer::Logger.instance # default
config.logstash_url = 'redis://localhost:6379' # if using default logger in production
end
See
lib/start_her/configuration.rb
for all configuration variables.
Usage
Publisher
class MyClass
include StartHer::Publisher
def do_something
# ...
reliable_publish('channel_one', 'succeed') # or publish('channel_one', 'succeed') for non persistent events
end
end
By default Redis has no persistent PubSub, so a simple mechanism is implemented to attempt to resolve this.
- Each day a new persistent backlog is created for a given channel
- Each backlog lives one week according to
StartHer.config.backlog_ttl
Subscriber
bundle exec starther ./lib/path/to/subscriber.rb
Note: You need to put your subscriber.rb
file into the lib
directory.
class Subscriber
include StartHer::Subscriber
# Defaults are defined by StartHer::Subscriber::DEFAULT_OPTS
channels: ['channel_one', 'channel_two']
# Customization of error
#
# This block is not mandatory
subscriber_error do |error|
# do something with error
end
# Perform an action when Subscriber subscribes on a channel
#
# This block is not mandatory
subscriber_on_psubscribe do |channel|
# do something at channel subscription time
end
# Customization of heartbeat response
# Each instance of Subscriber listens `hb_ping' channel and sends a response on `hb_pong'
# channel for service heartbeat
#
# This block is not mandatory
subscriber_heartbeat do |response|
# do something with response
end
def (channel, )
# your custom stuff here
end
end
Heartbeat ping message format:
{
"id": "643976ec-fc7c-4cd8-95bb-85a74f1987de",
"generated_at": "2015-11-23 10:34:05 UTC",
"data": {
"id": "058e216d5ce76492b574b39584d0676f359207e05a6a1dd30f238fc5604a66b2",
"generated_at": "2015-11-23 10:34:05 UTC",
"service_name": "MyPingService",
"version": "0.0.1"
}
}
Testing
StartHer provides a few options for testing your micro-service.
Setup
StartHer allows you to dynamically configure the testing harness with the following methods:
require 'start_her/testing'
StartHer::Testing.fake! # fake is the default mode
# StartHer::Testing.disable!
RSpec.configure do |config|
config.before(:each) do
StartHer::Testing.clear_stubed_redis
end
end
To query the current state, use the following methods:
StartHer::Testing.fake?
StartHer::Testing.disable?
Testing PubSub
require 'start_her/testing'
describe Subscriber do
let(:publisher) do
->(chan, msg) { Object.new.extend(StartHer::Publisher).reliable_publish(chan, msg) }
end
let(:chan) { 'channel_one' }
let(:msg) { 'my message' }
describe '#process_message' do
it 'processes message' do
expect(subject).to receive(:process_message).with(chan, msg)
publisher.call(chan, msg)
end
end
end
TODO
- Create an option wich enables a subscriber to receive the same message only once (avoid message replay due to reliable push)
- Implement scafolding for create a new project (like a gem) or for initialize a new Rails project
LICENSE
MIT
Contributing
- Fork it
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create new Pull Request