Browse Source

Add region commmand and projection

feature/region_center
Bèr Kessels 4 months ago
parent
commit
f588e1d4c4
3 changed files with 114 additions and 13 deletions
  1. 18
    13
      Rakefile
  2. 35
    0
      app/commands/add_region_command.rb
  3. 61
    0
      app/projections/region.rb

+ 18
- 13
Rakefile View File

@@ -6,6 +6,14 @@ def production?
ENV['APP_ENV'] == 'production'
end

def projectors
[
Hours::Projections::Places::Projector.new,
Hours::Projections::Addresses::Projector.new,
Hours::Projections::Regions::Projector.new
]
end

task :environment do
require 'lib/hours'
end
@@ -29,17 +37,14 @@ end

desc 'Run Event Stream Processors'
task run_processors: :environment do
# Need to disconnect before starting the processors so
# that the forked processes have their own connection / fork safety.
# Need to disconnect before starting the
# processors so that the forked processes have their own connection / fork
# safety.
Hours.projections_database.disconnect

esps = [
Hours::Projections::Places::Projector.new
]

# The ESPRunner will fork child processes for each of the ESPs passed to it.
EventSourcery::EventProcessing::ESPRunner.new(
event_processors: esps,
event_processors: projectors,
event_source: Hours.event_source
).start!
end
@@ -67,17 +72,17 @@ namespace :db do
end
end

desc 'Re Create Event Store datatabase and tables'
desc 'Create Event Store datatabase and tables'
task event_store: :environment do
database = EventSourcery::Postgres.config.event_store_database
EventSourcery::Postgres::Schema.create_event_store(db: database)
end

desc 'Re Create Projections database and tables'
task projections: :environment do
Hours::Projections::Places::Projector.new.setup
Hours::Projections::Addresses::Projector.new.setup
end
desc 'Create Projections database and tables'
task(projections: :environment) { projectors.each(&:setup) }
desc 'Reset Projections'
task(reset: :environment) { projectors.each(&:reset) }
end

namespace :db do

+ 35
- 0
app/commands/add_region_command.rb View File

@@ -0,0 +1,35 @@
# frozen_string_literal: true

module Hours
##
# Handles the command to add a new region.
# To be determined by caller if a GeoJSON object is a region or place
class AddRegionCommand
attr_reader :payload

def self.build(**args)
new(**args).tap(&:validate)
end

def initialize(params)
@params = params
@payload = params.slice(
:type,
:geometry,
:properties
)
end

def aggregate_class
Aggregates::Region
end

def validate
true
end

def aggregate_id
@aggregate_id ||= Hours::Aggregates::Place.aggregate_id_for(payload)
end
end
end

+ 61
- 0
app/projections/region.rb View File

@@ -0,0 +1,61 @@
# frozen_string_literal: true

require Hours.base_path.join('app', 'events', 'region_added.rb')

require 'babosa'

module Hours
module Projections
module Regions
##
# Handles the region projection
class Projector
include EventSourcery::Postgres::Projector

projector_name :regions

table :query_regions do
column :id, 'UUID NOT NULL', primary_key: true
column :name, :text
column :slug, :varchar, null: false, size: 255
column :centerpoint, 'geography(POINT)'

index :slug, unique: true
end

project RegionAdded do |event|
body = Hashie.symbolize_keys(event.body)
properties = body[:properties]
# Create slug

name = body[:properties][:name]
next unless name

slug = body[:properties][:name].to_slug.normalize.to_s
next unless slug

nonce = 0
# Ensure the slug is unique. Add numbers untill it is unique
loop do
break if table.where(slug: slug).empty?

slug = "#{body[:properties][:name]} #{nonce += 1}"
.to_slug.normalize.to_s
end

if table.where(id: event.aggregate_id).empty?
# Insert stuff
table.insert(
id: event.aggregate_id,
name: properties[:name],
centerpoint: GeoRuby::SimpleFeatures::Point.from_coordinates(
body[:geometry][:coordinates]
),
slug: slug
)
end
end
end
end
end
end

Loading…
Cancel
Save