Module: EventStore

Defined in:
lib/event_store.rb,
lib/event_store/client.rb,
lib/event_store/errors.rb,
lib/event_store/version.rb,
lib/event_store/snapshot.rb,
lib/event_store/aggregate.rb,
lib/event_store/time_hacker.rb,
lib/event_store/event_stream.rb

Defined Under Namespace

Classes: Aggregate, AttributeMissingError, Client, ConcurrencyError, Event, EventStream, SerializedEvent, Snapshot, TimeHacker

Constant Summary collapse

SNAPSHOT_DELIMITER =
"__NexEvStDelim__"
SNAPSHOT_KEY_DELIMITER =
":"
NO_SUB_KEY =
"NO_SUB_KEY"
VERSION =
'0.11.3'

Class Method Summary collapse

Class Method Details

.clear!Object



111
112
113
114
115
116
# File 'lib/event_store.rb', line 111

def self.clear!
  return unless connected?
  EventStore.db.from(fully_qualified_table).delete
  EventStore.db.from(fully_qualified_names_table).delete
  @redis.map(&:flushdb)
end

.connect(*args) ⇒ Object



49
50
51
# File 'lib/event_store.rb', line 49

def self.connect(*args)
  @db ||= Sequel.connect(*args)
end

.connect_dbObject



175
176
177
# File 'lib/event_store.rb', line 175

def self.connect_db
  self.connect(@db_config)
end

.connected?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/event_store.rb', line 107

def self.connected?
  !!EventStore.db
end

.create_dbObject



179
180
181
182
183
184
# File 'lib/event_store.rb', line 179

def self.create_db
  connect_db
  table = Sequel.qualify(schema, "schema_info")
  @db.run("CREATE SCHEMA IF NOT EXISTS #{schema}")
  Sequel::Migrator.run(@db, File.expand_path(File.join('..','..','db', self.migrations_dir), __FILE__), table: table)
end

.custom_config(database_config, redis_config, table_name = 'events', environment = 'production') ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/event_store.rb', line 152

def self.custom_config(database_config, redis_config, table_name = 'events', environment = 'production')
  database_config = database_config.each_with_object({}) {|(k,v), memo| memo[k.to_s] = v}
  redis_config    = redis_config.each_with_object({}) {|(k,v), memo| memo[k.to_s] = v}

  self.redis_connect(redis_config)

  @adapter         = database_config["adapter"].to_s
  @environment     = environment
  @db_config       = database_config
  @table_name      = table_name
  @schema          = database_config["schema"].to_s
  @use_names_table = database_config.fetch("use_names_table", true)
  connect_db
end

.dbObject



40
41
42
# File 'lib/event_store.rb', line 40

def self.db
  @db
end

.db_configObject



26
27
28
# File 'lib/event_store.rb', line 26

def self.db_config
  raw_db_config[@environment.to_s][@adapter.to_s]
end

.escape_bytea(binary_string) ⇒ Object



143
144
145
# File 'lib/event_store.rb', line 143

def self.escape_bytea(binary_string)
  binary_string.unpack('H*').join
end

.fully_qualified_names_tableObject



103
104
105
# File 'lib/event_store.rb', line 103

def self.fully_qualified_names_table
  @fully_qualified_names_table ||= Sequel.lit "#{schema}.#{lookup_table_name}"
end

.fully_qualified_tableObject



95
96
97
# File 'lib/event_store.rb', line 95

def self.fully_qualified_table
  @fully_qualified_table ||= qualified_table_name
end

.insert_table_name(date) ⇒ Object



72
73
74
75
76
77
# File 'lib/event_store.rb', line 72

def self.insert_table_name(date)
  return fully_qualified_table unless partitioning?

  partition_name = date.strftime("#{table_name}#{partition_name_suffix}")
  qualified_table_name(partition_name)
end

.local_redis_configObject



64
65
66
# File 'lib/event_store.rb', line 64

def self.local_redis_config
  @redis_connection ||= raw_db_config['redis']
end

.lookup_table_nameObject



91
92
93
# File 'lib/event_store.rb', line 91

def self.lookup_table_name
  @lookup_table_name ||= raw_db_config['lookup_table_name'] || "fully_qualified_names"
end

.migrations_dirObject



171
172
173
# File 'lib/event_store.rb', line 171

def self.migrations_dir
  @adapter == 'vertica' ? 'migrations' : 'pg_migrations'
end

.partition_name_suffixObject



83
84
85
# File 'lib/event_store.rb', line 83

def self.partition_name_suffix
  @db_config["partition_name_suffix"]
end

.partitioning?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/event_store.rb', line 79

def self.partitioning?
  @db_config["partitioning"]
end

.postgres(environment = 'test', table_name = 'events', schema = 'event_store_test') ⇒ Object



118
119
120
121
122
123
124
125
# File 'lib/event_store.rb', line 118

def self.postgres(environment = 'test', table_name = 'events', schema = 'event_store_test')
  @schema         = schema
  @table_name     = table_name
  @environment    = environment.to_s
  @adapter        = 'postgres'
  @db_config      ||= self.db_config
  custom_config(@db_config, local_redis_config, @table_name, environment)
end

.qualified_table_name(name = table_name) ⇒ Object



99
100
101
# File 'lib/event_store.rb', line 99

def self.qualified_table_name(name = table_name)
  Sequel.lit "#{schema}.#{name}"
end

.raw_db_configObject



30
31
32
33
34
35
36
37
38
# File 'lib/event_store.rb', line 30

def self.raw_db_config
  if @raw_db_config.nil?
    file_path = File.expand_path(__FILE__ + '/../../db/database.yml')
    @config_file = File.open(file_path,'r')
    @raw_db_config = YAML.load(@config_file)
    @config_file.close
  end
  @raw_db_config
end

.redis(hostname) ⇒ Object



44
45
46
47
# File 'lib/event_store.rb', line 44

def self.redis(hostname)
  hash = Zlib::crc32(hostname)
  @redis[hash % @redis.length]
end

.redis_connect(config_hash) ⇒ Object



53
54
55
56
57
58
59
60
61
62
# File 'lib/event_store.rb', line 53

def self.redis_connect(config_hash)
  if config_hash["hosts"]
    generic_config = config_hash.reject { |k, _| k == "hosts" }
    @redis = config_hash["hosts"].map { |hostname|
      Redis.new(generic_config.merge("host" => hostname))
    }
  else
    @redis ||= [Redis.new(config_hash)]
  end
end

.schemaObject



68
69
70
# File 'lib/event_store.rb', line 68

def self.schema
  @schema ||= raw_db_config[@environment][@adapter]['schema']
end

.table_nameObject



87
88
89
# File 'lib/event_store.rb', line 87

def self.table_name
  @table_name ||= raw_db_config['table_name']
end

.unescape_bytea(binary_string) ⇒ Object



147
148
149
150
# File 'lib/event_store.rb', line 147

def self.unescape_bytea(binary_string)
  binary_string = [binary_string[1..-1]].pack("H*") if binary_string[0] == "x"
  [binary_string].pack("H*")
end

.use_names_table?Boolean

Returns:

  • (Boolean)


167
168
169
# File 'lib/event_store.rb', line 167

def self.use_names_table?
  @use_names_table
end

.vertica(environment = 'test', table_name = 'events', schema = 'event_store_test') ⇒ Object

To find the ip address of vertica on your local box (running in a vm)

  1. open Settings -> Network and select Wi-Fi

  2. open a terminal in the VM

  3. do /sbin/ifconfig (ifconfig is not in $PATH)

  4. the inet address for en0 is what you want

Hint: if it just hangs, you have have the wrong IP



133
134
135
136
137
138
139
140
141
# File 'lib/event_store.rb', line 133

def self.vertica(environment = 'test', table_name = 'events', schema = 'event_store_test')
  @schema         = schema
  @table_name     = table_name
  @environment    = environment.to_s
  @adapter        = 'vertica'
  @db_config      ||= self.db_config
  @db_config['host'] ||= ENV['VERTICA_HOST'] || vertica_host
  custom_config(@db_config, local_redis_config, @table_name, environment)
end

.vertica_hostObject



186
187
188
# File 'lib/event_store.rb', line 186

def self.vertica_host
  File.read File.expand_path(File.join('..','..','db', 'vertica_host_address.txt'), __FILE__)
end