Class: Petra::Components::LogEntry

Inherits:
Object
  • Object
show all
Includes:
Comparable, Util::FieldAccessors, Util::Registrable
Defined in:
lib/petra/components/log_entry.rb

Overview

A log entry is basically a struct with certain helper functions. This class contains some base functionality and a map of more specific log entry types.

Registered entry types may define own field_accessors which will be serialized when persisting the log entries.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util::FieldAccessors

#[], #[]=, #fields, included

Methods included from Util::Registrable

included

Constructor Details

#initialize(section, **fields) ⇒ LogEntry

Initializes a new log entry based on the given section and options

Parameters:

  • fields (Hash)
  • options (Hash)

    a customizable set of options



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/petra/components/log_entry.rb', line 92

def initialize(section, **fields)
  @section = section

  @object_persisted      = fields.delete(:object_persisted)
  @transaction_persisted = fields.delete(:transaction_persisted)

  # Restore the given field accessors
  fields.each do |k, v|
    send("#{k}=", v)
  end

  self.savepoint              ||= section.savepoint
  self.transaction_identifier ||= section.transaction.identifier
end

Instance Attribute Details

#attributeObject (readonly)

Returns the value of attribute attribute.



38
39
40
# File 'lib/petra/components/log_entry.rb', line 38

def attribute
  @attribute
end

#object_classObject (readonly)

Identifies the object the changes were performed on, e.g. “User”, 1 for @user.save The object class is also needed to load the corresponding class configuration



37
38
39
# File 'lib/petra/components/log_entry.rb', line 37

def object_class
  @object_class
end

#object_persistedObject Also known as: object_persisted?

Means that the client persisted the object referenced by this log entry, e.g. through #save in case of AR



44
45
46
# File 'lib/petra/components/log_entry.rb', line 44

def object_persisted
  @object_persisted
end

#persist_on_retry=(value) ⇒ Object (writeonly)

Marks this log entry to be persisted on section retries even if the object was not persisted



47
48
49
# File 'lib/petra/components/log_entry.rb', line 47

def persist_on_retry=(value)
  @persist_on_retry = value
end

#sectionObject (readonly)

Returns the value of attribute section.



52
53
54
# File 'lib/petra/components/log_entry.rb', line 52

def section
  @section
end

#transaction_persistedObject Also known as: transaction_persisted?

Means that the log entry was actually persisted within the transaction



50
51
52
# File 'lib/petra/components/log_entry.rb', line 50

def transaction_persisted
  @transaction_persisted
end

Class Method Details

.from_hash(section, fields) ⇒ Petra::Components::LogEntry

Builds a log entry from the given section and hash, but automatically sets the persistence flags



182
183
184
185
186
187
188
# File 'lib/petra/components/log_entry.rb', line 182

def self.from_hash(section, fields)
  log!(fields.delete('kind'),
       section: section,
       object_persisted: true,
       transaction_persisted: true,
       **fields.symbolize_keys)
end

.log!(kind, section:, **fields) ⇒ Object



58
59
60
61
# File 'lib/petra/components/log_entry.rb', line 58

def self.log!(kind, section:, **fields)
  fail ArgumentError, "#{kind} is not a valid entry type" unless registered_entry_type?(kind)
  registered_entry_type(kind).new(section, **fields)
end

Instance Method Details

#<=>(other) ⇒ Object

If both entries were made in the same section, the smaller entry was generated earlier than the other. If both entries are in different sections, the one with a smaller savepoint version is considered smaller.



113
114
115
116
117
118
119
# File 'lib/petra/components/log_entry.rb', line 113

def <=>(other)
  if section == other.section
    section.log_entries.index(self) <=> section.log_entries.index(other)
  else
    section.savepoint_version <=> other.section.savepoint_version
  end
end

#apply!Object

Applies the action performed in the current log entry to the corresponding object



249
250
251
# File 'lib/petra/components/log_entry.rb', line 249

def apply!
  not_implemented # nop?
end

#attribute_change?Boolean


Internal Field Handling

Returns:

  • (Boolean)


125
126
127
# File 'lib/petra/components/log_entry.rb', line 125

def attribute_change?
  kind?(:attribute_change)
end

#attribute_read?Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/petra/components/log_entry.rb', line 129

def attribute_read?
  kind?(:attribute_read)
end

#enqueue_for_persisting!Object

Adds the log entry to the persistence queue if the following conditions are met:

  1. The log entry has to be marked as ‘object_persisted’, meaning that the object was saved during/after the action which created the the entry

  2. The log entry hasn’t been persisted previously

This does not automatically mark this log entry as persisted, this is done once the persistence adapter finished its work



218
219
220
221
222
# File 'lib/petra/components/log_entry.rb', line 218

def enqueue_for_persisting!
  return if transaction_persisted?
  return unless persist? || persist_on_retry? && transaction.retry_in_progress?
  Petra.transaction_manager.persistence_adapter.enqueue(self)
end

#for_object?(object_key) ⇒ Boolean

Returns true if this log entry was made in the context of the given object (key).

Returns:

  • (Boolean)

    true if this log entry was made in the context of the given object (key)



193
194
195
# File 'lib/petra/components/log_entry.rb', line 193

def for_object?(object_key)
  self.object_key == object_key
end

#kind?(kind) ⇒ Boolean

Returns true if this log entry is of the given kind.

Returns:

  • (Boolean)

    true if this log entry is of the given kind



200
201
202
# File 'lib/petra/components/log_entry.rb', line 200

def kind?(kind)
  self.class.kind.to_s == kind.to_s
end

#load_proxyPetra::Proxies::ObjectProxy

Returns the proxy this log entry was made for.

Returns:



269
270
271
272
273
# File 'lib/petra/components/log_entry.rb', line 269

def load_proxy
  @load_proxy ||= transaction.objects.fetch(object_key) do
    new_object? ? initialize_proxy : restore_proxy
  end
end

#mark_as_object_persisted!Object



141
142
143
# File 'lib/petra/components/log_entry.rb', line 141

def mark_as_object_persisted!
  @object_persisted = true
end

#mark_as_persisted!(identifier) ⇒ Object



145
146
147
148
# File 'lib/petra/components/log_entry.rb', line 145

def mark_as_persisted!(identifier)
  @transaction_persisted = true
  @entry_identifier      = identifier
end

#marked_for_destruction?Boolean

Returns true if this log entry should be destroyed if it is enqueued for the next persisting phase.

Returns:

  • (Boolean)

    true if this log entry should be destroyed if it is enqueued for the next persisting phase



154
155
156
# File 'lib/petra/components/log_entry.rb', line 154

def marked_for_destruction?
  !!@marked_for_destruction
end

#object_initialization?Boolean

Returns:

  • (Boolean)


137
138
139
# File 'lib/petra/components/log_entry.rb', line 137

def object_initialization?
  kind?(:object_initialization)
end

#object_persistence?Boolean

Returns:

  • (Boolean)


133
134
135
# File 'lib/petra/components/log_entry.rb', line 133

def object_persistence?
  kind?(:object_persistence)
end

#persist?Boolean

May be overridden by more specialized log entries, the basic version will persist an entry as long as it is marked as object persisted

Returns:

  • (Boolean)


237
238
239
# File 'lib/petra/components/log_entry.rb', line 237

def persist?
  object_persisted?
end

#persist_on_retry?boolean

Returns If this returns true, the log entry will be persisted when a section is retried even if #persist? would return false.

Returns:

  • (boolean)

    If this returns true, the log entry will be persisted when a section is retried even if #persist? would return false



228
229
230
# File 'lib/petra/components/log_entry.rb', line 228

def persist_on_retry?
  !!@persist_on_retry
end

#to_h(**options) ⇒ Hash

Information about the object / transaction persistence is not kept as this method will only be used during persistence or on already persisted entries

Parameters:

  • options (Hash)

Options Hash (**options):

  • :entry_identifier (String)

    A section-unique identifier for the current log entry. It is usually given by the used persistence adapter.

Returns:

  • (Hash)

    the necessary information about this entry to reproduce it later The result is mainly used when serializing the step later.



171
172
173
174
175
# File 'lib/petra/components/log_entry.rb', line 171

def to_h(**options)
  fields.each_with_object(options.merge('kind' => self.class.kind)) do |(k, v), h|
    h[k] = v unless v.nil?
  end
end

#to_sObject



275
276
277
# File 'lib/petra/components/log_entry.rb', line 275

def to_s
  "#{section.savepoint}/#{@object_id} => #{self.class.kind}"
end

#undo!Object

Tries to undo a previously done #apply! This is currently only possible for attribute changes as we do not know how to undo destruction / persistence for general objects



258
259
260
# File 'lib/petra/components/log_entry.rb', line 258

def undo!
  load_proxy.send(:__undo_application__, self)
end