Class: PgEventstore::Utils

Inherits:
Object
  • Object
show all
Defined in:
lib/pg_eventstore/utils.rb,
sig/pg_eventstore/utils.rbs,
ext/pg_eventstore_ext/pg_eventstore_ext.c

Class Method Summary collapse

Class Method Details

.assert!(truthy, message = nil) ⇒ void

This method returns an undefined value.

Parameters:

  • truthy (boolish)
  • message (String, nil) (defaults to: nil)

Raises:

  • ArgumentError



141
142
143
# File 'lib/pg_eventstore/utils.rb', line 141

def assert!(truthy, message = nil)
  raise ArgumentError, message unless truthy
end

.assert_node_role!(config, expected_roles) ⇒ void

This method returns an undefined value.

Parameters:



154
155
156
157
158
# File 'lib/pg_eventstore/utils.rb', line 154

def assert_node_role!(config, expected_roles)
  return if expected_roles.include?(config.eventstore_role)

  raise "You can't perform this operation on #{config.eventstore_role.inspect} node!"
end

.benchmark { ... } ⇒ Float

Yields the given block and measures its execution time

Yields:

Yield Returns:

  • (Object)

Returns:

  • (Float)

    number of seconds the block took to execute



132
133
134
135
136
# File 'lib/pg_eventstore/utils.rb', line 132

def benchmark
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  yield
  Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
end

.deep_dup(object) ⇒ Object

Deep dup Array or Hash

Parameters:

  • object (Object)

Returns:

  • (Object)


25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/pg_eventstore/utils.rb', line 25

def deep_dup(object)
  case object
  when Hash
    object.each_with_object({}) do |(key, value), result|
      result[deep_dup(key)] = deep_dup(value)
    end
  when Array
    object.map { |e| deep_dup(e) }
  else
    object.dup
  end
end

.deep_transform_keys(object) {|key| ... } ⇒ Object

Deep transforms keys of a given Hash

Parameters:

  • object (Object)

Yields:

Yield Parameters:

  • key (Object)

Yield Returns:

  • (Object)

Returns:

  • (Object)

    a hash with transformed keys



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/pg_eventstore/utils.rb', line 9

def deep_transform_keys(object, &block)
  case object
  when Hash
    object.each_with_object({}) do |(key, value), result|
      result[yield(key)] = deep_transform_keys(value, &block)
    end
  when Array
    object.map { |e| deep_transform_keys(e, &block) }
  else
    object
  end
end

.deprecation_warning(message) ⇒ void

This method returns an undefined value.

Parameters:

  • message (String)


78
79
80
# File 'lib/pg_eventstore/utils.rb', line 78

def deprecation_warning(message)
  PgEventstore.logger&.warn("\e[31m[DEPRECATED]: #{message}\e[0m")
end

.error_info(error) ⇒ Hash

Transforms exception instance into a hash

Parameters:

  • error (StandardError)

Returns:

  • (Hash)


48
49
50
51
52
53
54
55
56
57
# File 'lib/pg_eventstore/utils.rb', line 48

def error_info(error)
  original_error = unwrap_exception(error)
  {
    class: original_error.class,
    message: original_error.message,
    backtrace: original_error.backtrace,
  }.tap do |attrs|
    attrs.merge!(error.extra) if error.is_a?(WrappedException)
  end
end

.missing_implementation!(obj) ⇒ void

This method returns an undefined value.

Parameters:

  • obj

Raises:

  • NotImplementedError



147
148
149
# File 'lib/pg_eventstore/utils.rb', line 147

def missing_implementation!(obj)
  raise NotImplementedError, obj.inspect
end

.original_global_position(raw_event) ⇒ Integer

Detect the global position of the event record in the database. If it is a link event - we pick a global_position of the link instead of picking a global_position of an event this link points to.

Parameters:

  • raw_event (Hash)

Returns:

  • (Integer)


72
73
74
# File 'lib/pg_eventstore/utils.rb', line 72

def original_global_position(raw_event)
  raw_event['link'] ? raw_event['link']['global_position'] : raw_event['global_position']
end

.positional_vars(array) ⇒ String

Converts array to the string containing SQL positional variables

Parameters:

  • array (Array)

Returns:

  • (String)

    positional variables, based on array size. Example: "$1, $2, $3"



41
42
43
# File 'lib/pg_eventstore/utils.rb', line 41

def positional_vars(array)
  array.size.times.map { |t| "$#{t + 1}" }.join(', ')
end

.range_to_slice(partition_ids, max_partitions_per_call) ⇒ Object

Loops through the given array of partition ids to find an index at which we have up to max_partitions_per_call unique partitions. Ruby representation of this implementation looks like this:

def range_to_slice2(partition_ids, max_partitions_per_call)
return (0..) if partition_ids.size <= max_partitions_per_call

partitions_map = {}
latest_index = nil
partition_ids.each_with_index do |partition_id, index|
  partitions_map[partition_id] = true
  if partitions_map.size > max_partitions_per_call
    latest_index = index - 1
    break
  end
end
0..latest_index
end

It was extracted into C extension because of performance of ruby loops - they are deadly slow comparing to C loops. The performance gain is x5-x15 times faster comparing to ruby implementation. Because we need to do this operation on each read command - it worth having it here.



165
166
167
# File 'lib/pg_eventstore/utils.rb', line 165

def range_to_slice(partition_ids, max_partitions_to_resolve_per_call)
  # This is stub, used for indexing
end

.read_pid(file_path) ⇒ String?

rubocop:disable Lint/SuppressedException

Parameters:

  • file_path (String)

Returns:

  • (String, nil)


104
105
106
107
108
109
110
# File 'lib/pg_eventstore/utils.rb', line 104

def read_pid(file_path)
  file = File.open(file_path, 'r')
  file.readline.strip
rescue Errno::ENOENT
ensure
  file&.close
end

.remove_file(file_path) ⇒ void

This method returns an undefined value.

rubocop:disable Lint/SuppressedException

Parameters:

  • file_path (String)


95
96
97
98
# File 'lib/pg_eventstore/utils.rb', line 95

def remove_file(file_path)
  File.delete(file_path)
rescue Errno::ENOENT
end

.underscore_str(str) ⇒ String

Parameters:

  • str (String)

Returns:

  • (String)


61
62
63
64
65
66
# File 'lib/pg_eventstore/utils.rb', line 61

def underscore_str(str)
  str = str.dup
  str[0] = str[0].downcase
  str.gsub!(/[A-Z]/) { |letter| "_#{letter.downcase}" }
  str
end

.unwrap_exception(wrapped_exception) ⇒ StandardError

Parameters:

Returns:

  • (StandardError)


124
125
126
127
128
# File 'lib/pg_eventstore/utils.rb', line 124

def unwrap_exception(wrapped_exception)
  return wrapped_exception.original_exception if wrapped_exception.is_a?(WrappedException)

  wrapped_exception
end

.wrap_exception(exception, **extra) ⇒ PgEventstore::WrappedException

Wraps subscription handler exception to correctly differentiate it from other errors that may happen inside the implementation. This is needed to correctly handle subscription handler errors vs internal errors.

Parameters:

  • exception (StandardError)
  • extra (Hash)

    additional exception info

Returns:



118
119
120
# File 'lib/pg_eventstore/utils.rb', line 118

def wrap_exception(exception, **extra)
  WrappedException.new(exception, extra)
end

.write_to_file(file_path, content) ⇒ void

This method returns an undefined value.

Parameters:

  • file_path (String)
  • content (String)


85
86
87
88
89
90
# File 'lib/pg_eventstore/utils.rb', line 85

def write_to_file(file_path, content)
  file = File.open(file_path, 'w')
  file.write(content)
ensure
  file&.close
end