Module: Readyset

Defined in:
lib/readyset.rb,
lib/readyset/error.rb,
lib/readyset/query.rb,
lib/readyset/caches.rb,
lib/readyset/explain.rb,
lib/readyset/railtie.rb,
lib/readyset/version.rb,
lib/readyset/configuration.rb,
lib/readyset/model_extension.rb,
lib/readyset/query/queryable.rb,
lib/readyset/query/cached_query.rb,
lib/readyset/relation_extension.rb,
lib/readyset/health/healthchecks.rb,
lib/readyset/query/proxied_query.rb,
lib/readyset/controller_extension.rb,
lib/readyset/health/healthchecker.rb,
lib/readyset/utils/window_counter.rb

Overview

The Readyset module provides functionality to integrate ReadySet caching with Ruby on Rails applications. It offers methods to configure and manage ReadySet caches, as well as to route database queries through ReadySet.

Defined Under Namespace

Modules: ControllerExtension, Error, Health, ModelExtension, Query, RelationExtension, Utils Classes: Caches, Configuration, Explain, Railtie

Constant Summary collapse

VERSION =
'0.1.1'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Attribute Details

#configuration=(value) ⇒ Object (writeonly)

Sets the configuration for Readyset.



24
25
26
# File 'lib/readyset.rb', line 24

def configuration=(value)
  @configuration = value
end

Class Method Details

.configurationReadyset::Configuration Also known as: config

Retrieves the Readyset configuration, initializing it if it hasn’t been set yet.

Returns:



28
29
30
# File 'lib/readyset.rb', line 28

def self.configuration
  @configuration ||= Configuration.new
end

.configure {|configuration| ... } ⇒ Object

Configures Readyset by providing a block with configuration details.

Yield Parameters:

Yield Returns:

  • (void)


39
40
41
# File 'lib/readyset.rb', line 39

def self.configure
  yield configuration
end

.create_cache!(id: nil, sql: nil, name: nil, always: false) ⇒ void

This method returns an undefined value.

Creates a new cache on ReadySet using the given ReadySet query ID or SQL query. queries to these caches will never fall back to the database if this is true.

Parameters:

  • id (String) (defaults to: nil)

    the ReadySet query ID of the query from which a cache should be created.

  • sql (String) (defaults to: nil)

    the SQL string from which a cache should be created.

  • name (String) (defaults to: nil)

    the name for the cache being created.

  • always (Boolean) (defaults to: false)

    whether the cache should always be used;

Raises:

  • (ArgumentError)

    raised if exactly one of the ‘id` or `sql` arguments was not provided.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/readyset.rb', line 51

def self.create_cache!(id: nil, sql: nil, name: nil, always: false)
  if (sql.nil? && id.nil?) || (!sql.nil? && !id.nil?)
    raise ArgumentError, 'Exactly one of the `id` and `sql` parameters must be provided'
  end

  connection = Readyset.route { ActiveRecord::Base.connection }
  from =
    if sql
      sql
    else
      connection.quote_column_name(id)
    end

  if always && name
    quoted_name = connection.quote_column_name(name)
    raw_query("CREATE CACHE ALWAYS #{quoted_name} FROM #{from}")
  elsif always
    raw_query("CREATE CACHE ALWAYS FROM #{from}")
  elsif name
    quoted_name = connection.quote_column_name(name)
    raw_query("CREATE CACHE #{quoted_name} FROM #{from}")
  else
    raw_query("CREATE CACHE FROM #{from}")
  end

  nil
end

.drop_cache!(name) ⇒ void

This method returns an undefined value.

Drops an existing cache on ReadySet using the given query name.

Parameters:

  • name (String)

    the name of the cache that should be dropped.



82
83
84
85
86
87
88
# File 'lib/readyset.rb', line 82

def self.drop_cache!(name)
  connection = Readyset.route { ActiveRecord::Base.connection }
  quoted_name = connection.quote_column_name(name)
  raw_query("DROP CACHE #{quoted_name}")

  nil
end

.explain(query) ⇒ Explain

Gets information about the given query from ReadySet, including whether it’s supported to be cached, its current status, the rewritten query text, and the query ID.

The information about the given query is retrieved by invoking ‘EXPLAIN CREATE CACHE FROM` on ReadySet.

Parameters:

  • a (String)

    query about which information should be retrieved

Returns:



98
99
100
# File 'lib/readyset.rb', line 98

def self.explain(query)
  Explain.call(query)
end

.raw_query(query) ⇒ Object

:nodoc:



110
111
112
113
114
# File 'lib/readyset.rb', line 110

def self.raw_query(query) # :nodoc:
  ActiveRecord::Base.connected_to(role: writing_role, shard: shard, prevent_writes: false) do
    ActiveRecord::Base.connection.execute(query)
  end
end

.raw_query_sanitize(*sql_array) ⇒ PG::Result

Note:

This method is not part of the public API.

Executes a raw SQL query against ReadySet. The query is sanitized prior to being executed.

Parameters:

  • sql_array (Array<Object>)

    the SQL array to be executed against ReadySet.

Returns:

  • (PG::Result)

    the result of executing the SQL query.



106
107
108
# File 'lib/readyset.rb', line 106

def self.raw_query_sanitize(*sql_array) # :nodoc:
  raw_query(ActiveRecord::Base.sanitize_sql_array(sql_array))
end

.route(prevent_writes: true) { ... } ⇒ Object

Routes to ReadySet any queries that occur in the given block. the connection to ReadySet.

Parameters:

  • prevent_writes (Boolean) (defaults to: true)

    if true, prevents writes from being executed on

Yields:

  • a block whose queries should be routed to ReadySet.

Returns:

  • the value of the last line of the block.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/readyset.rb', line 121

def self.route(prevent_writes: true, &block)
  if healthchecker.healthy?
    begin
      if prevent_writes
        ActiveRecord::Base.connected_to(role: reading_role, shard: shard, prevent_writes: true,
          &block)
      else
        ActiveRecord::Base.connected_to(role: writing_role, shard: shard, prevent_writes: false,
          &block)
      end
    rescue => e
      healthchecker.process_exception(e)
      raise e
    end
  else
    yield
  end
end