class WCC::Contentful::Store::Base

This is the base class for stores which implement index, and therefore must be kept up-to-date via the Sync API. @abstract At a minimum subclasses should override {#find}, {#execute}, {#set},

and #{delete}. As an alternative to overriding set and delete, the subclass
can override {#index}.  Index is called when a webhook triggers a sync, to
update the store.

To implement a new store, you should include the rspec_examples in your rspec tests for the store. See spec/wcc/contentful/store/memory_store_spec.rb for an example.

Attributes

mutex[R]

Public Class Methods

new() click to toggle source
# File lib/wcc/contentful/store/base.rb, line 110
def initialize
  @mutex = Concurrent::ReentrantReadWriteLock.new
end

Public Instance Methods

delete(_id) click to toggle source

Removes the entry by ID from the store. @abstract

# File lib/wcc/contentful/store/base.rb, line 28
def delete(_id)
  raise NotImplementedError, "#{self.class} does not implement #delete"
end
ensure_hash(val) click to toggle source
# File lib/wcc/contentful/store/base.rb, line 114
def ensure_hash(val)
  raise ArgumentError, 'Value must be a Hash' unless val.is_a?(Hash)
end
execute(_query) click to toggle source

Executes a WCC::Contentful::Store::Query object created by {#find_all} or {#find_by}. Implementations should override this to translate the query's conditions into a query against the datastore.

For a very naiive implementation see WCC::Contentful::Store::MemoryStore#execute @abstract

# File lib/wcc/contentful/store/base.rb, line 38
def execute(_query)
  raise NotImplementedError, "#{self.class} does not implement #execute"
end
find_all(content_type:, options: nil) click to toggle source

Finds all entries of the given content type. A content type is required.

Subclasses may override this to provide their own query implementation,

or else override #execute to run the query after it has been parsed.

@param [String] content_type The ID of the content type to search for. @param [Hash] options An optional set of additional parameters to the query

defining for example include depth.  Not all store implementations respect all options.

@return [Query] A query object that exposes methods to apply filters

# File lib/wcc/contentful/store/base.rb, line 102
def find_all(content_type:, options: nil)
  Query.new(
    self,
    content_type: content_type,
    options: options
  )
end
find_by(content_type:, filter: nil, options: nil) click to toggle source

Finds the first entry matching the given filter. A content type is required.

@param [String] content_type The ID of the content type to search for. @param [Hash] filter A set of key-value pairs defining filter operations.

See WCC::Contentful::Store::Base::Query

@param [Hash] options An optional set of additional parameters to the query

defining for example include depth.  Not all store implementations respect all options.
# File lib/wcc/contentful/store/base.rb, line 87
def find_by(content_type:, filter: nil, options: nil)
  # default implementation - can be overridden
  q = find_all(content_type: content_type, options: { limit: 1 }.merge!(options || {}))
  q = q.apply(filter) if filter
  q.first
end
index(json) click to toggle source

Processes a data point received via the Sync API. This can be a published entry or asset, or a 'DeletedEntry' or 'DeletedAsset'. The default implementation calls into set and delete to perform the appropriate operations in the store.

# File lib/wcc/contentful/store/base.rb, line 52
def index(json)
  # Subclasses can override to do this in a more performant thread-safe way.
  # Example: postgres_store could do this in a stored procedure for speed
  mutex.with_write_lock do
    prev =
      case type = json.dig('sys', 'type')
      when 'DeletedEntry', 'DeletedAsset'
        delete(json.dig('sys', 'id'))
      else
        set(json.dig('sys', 'id'), json)
      end

    if (prev_rev = prev&.dig('sys', 'revision')) && (next_rev = json.dig('sys', 'revision'))
      if next_rev < prev_rev
        # Uh oh! we overwrote an entry with a prior revision.  Put the previous back.
        return index(prev)
      end
    end

    case type
    when 'DeletedEntry', 'DeletedAsset'
      nil
    else
      json
    end
  end
end
index?() click to toggle source

Returns true if this store can persist entries and assets which are retrieved from the sync API.

# File lib/wcc/contentful/store/base.rb, line 44
def index?
  true
end
set(_id, _value) click to toggle source

Sets the value of the entry with the given ID in the store. @abstract

# File lib/wcc/contentful/store/base.rb, line 22
def set(_id, _value)
  raise NotImplementedError, "#{self.class} does not implement #set"
end