module Maitredee

Constants

Error
NoRoutesError
PublisherMessage
SubscriberMessage
VERSION
ValidationError

Attributes

app_name[W]

set app_name instead of using default @param [String]

client[R]

the client we use for publishing and setting up workers @return [Maitredee::Adapters::AbstractAdapter]

namespace[W]

set namespace instead of using default @param [String]

resource_name_suffix[RW]

allows you to add a suffix to all your resource names, mostly used for testing but could be useful in other occassions. @return [String] string appended to all resource names

schema_path[RW]

this is the path of the folder in which validation_schema will try to do a lookup. This folder should contain json schemas. @return [String] path to folder

Public Class Methods

app_name() click to toggle source

fetch configured app name or automatically fetch from Rails or from `ENV` used for generating queue_resource_name

@return [String]

# File lib/maitredee.rb, line 143
def app_name
  @app_name ||=
    begin
      rails_app_name =
        if defined?(Rails)
          Rails.application.class.parent_name.underscore.dasherize
        end
      ENV["MAITREDEE_APP_NAME"] ||
        rails_app_name ||
        raise("must set app_name for maitredee")
    end
end
client=(slug) click to toggle source

set a client without parameters

@param slug [#to_s] name of adapter

# File lib/maitredee.rb, line 76
def client=(slug)
  set_client(slug)
end
configure_broker() click to toggle source

idempotently configures broker to create topics, queues and subscribe queues to topics nothing will eveer be deleted or cleaned up

# File lib/maitredee.rb, line 174
def configure_broker
  hash_array = Hash.new { |hash, key| hash[key] = [] }
  topics_and_queues =
    subscriber_registry.each_with_object(hash_array) do |subscriber, hash|
      topic_arn = topic_resource_name(subscriber.topic_name)
      hash[topic_arn] << queue_resource_name(subscriber.topic_name, subscriber.queue_name)
    end
  client.configure_broker(topics_and_queues)
end
namespace() click to toggle source

fetch configured namespace or automatically fetch from `ENV` @return [String]

# File lib/maitredee.rb, line 163
def namespace
  @namespace ||=
    ENV["MAITREDEE_NAMESPACE"] || raise("must set namespace for maitredee")
end
publish( topic_name:, body:, schema_name:, event_name: nil, primary_key: nil ) click to toggle source

publishes messages using configured adapter

@param topic [String] topic name @param body [Hash, Array, String] Any valid json data that can be validated by json-schema @param schema_name [String] A valid schema name for publishing data @param event_name [String, nil] Event name for subscriber routing @param primary_key [#to_s, nil] Key to be used for resource identification

@return [PublisherMessage] published message

# File lib/maitredee.rb, line 39
def publish(
  topic_name:,
  body:,
  schema_name:,
  event_name: nil,
  primary_key: nil
)
  raise ArgumentError, "topic_name, body or schema_name is nil" if topic_name.nil? || body.nil? || schema_name.nil?
  validate!(body, schema_name)

  message = PublisherMessage.new(
    message_id: SecureRandom.uuid,
    topic_resource_name: topic_resource_name(topic_name),
    topic_name: topic_name.to_s,
    body: body,
    schema_name: schema_name&.to_s,
    event_name: event_name&.to_s,
    primary_key: primary_key&.to_s
  )

  client.publish(message)

  message
end
queue_resource_name(topic_name, queue_name) click to toggle source

build queue resource name from queue name and topic name

@param topic_name [#to_s] topic name @param queue_name [#to_s] queue name @return [String]

# File lib/maitredee.rb, line 97
def queue_resource_name(topic_name, queue_name)
  [
    namespace,
    topic_name,
    app_name,
    queue_name,
    resource_name_suffix
  ].compact.join("--").tap do |val|
    if val.length > 80
      raise "Cannot have a queue name longer than 80 characters: #{name}"
    end
  end
end
register_subscriber(klass) click to toggle source

@api private

# File lib/maitredee.rb, line 185
def register_subscriber(klass)
  client.add_worker(klass)
  subscriber_registry.add(klass)
end
schemas() click to toggle source

hash to look up schema based of schema_path

@return Hash

# File lib/maitredee.rb, line 132
def schemas
  @schemas ||= Hash.new do |hash, key|
    path = Pathname.new(schema_path).join("#{key}.json")
    hash[key] = JSONSchemer.schema(path)
  end
end
set_client(slug, *args) click to toggle source

configure the adapter, must be executed before loading subscribers

@param slug [#to_s] name of adapter @param args [] options to send to the adapter

# File lib/maitredee.rb, line 68
def set_client(slug, *args)
  raise "No client set for Maitredee" if slug.nil?
  @client = "::Maitredee::Adapters::#{slug.to_s.camelize}Adapter".constantize.new(*args)
end
subscriber_registry() click to toggle source

@api private

# File lib/maitredee.rb, line 191
def subscriber_registry
  @subscriber_registry ||= Set.new
end
topic_resource_name(topic_name) click to toggle source

build topic resource name from topic name

@param topic_name [#to_s] topic name @return [String]

# File lib/maitredee.rb, line 84
def topic_resource_name(topic_name)
  [
    namespace,
    topic_name,
    resource_name_suffix
  ].compact.join("--")
end
validate!(body, schema) click to toggle source

validate a body given a schema name

@param body [Array, Hash, String] data to send with message @param schema [String] string key to look up schema to validate against

@raise [ValidationError] if validation fails @return [nil]

# File lib/maitredee.rb, line 118
def validate!(body, schema)
  errors = schemas[schema].validate(deep_stringify_keys(body))
  properties = errors.map do |error|
    error["data_pointer"]
  end.join(", ")

  if errors.any?
    raise ValidationError, "Invalid properties: #{properties}"
  end
end

Private Class Methods

deep_stringify_keys(object) click to toggle source
# File lib/maitredee.rb, line 197
def deep_stringify_keys(object)
  case object
  when Hash
    object.each_with_object({}) do |(key, value), result|
      result[key.to_s] = deep_stringify_keys(value)
    end
  when Array
    object.map { |e| deep_stringify_keys(e) }
  else
    object
  end
end