Class: Gitlab::Database::LoadBalancing::Session

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/database/load_balancing/session.rb

Overview

Tracking of load balancing state per user session.

A session starts at the beginning of a request and ends once the request has been completed. Sessions can be used to keep track of what hosts should be used for queries.

Constant Summary collapse

CACHE_KEY =
:gitlab_load_balancer_session

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSession

Returns a new instance of Session.



26
27
28
29
30
31
32
# File 'lib/gitlab/database/load_balancing/session.rb', line 26

def initialize
  @use_primary = false
  @performed_write = false
  @ignore_writes = false
  @fallback_to_replicas_for_ambiguous_queries = false
  @use_replicas_for_read_queries = false
end

Class Method Details

.clear_sessionObject



18
19
20
# File 'lib/gitlab/database/load_balancing/session.rb', line 18

def self.clear_session
  RequestStore.delete(CACHE_KEY)
end

.currentObject



14
15
16
# File 'lib/gitlab/database/load_balancing/session.rb', line 14

def self.current
  RequestStore[CACHE_KEY] ||= new
end

.without_sticky_writes(&block) ⇒ Object



22
23
24
# File 'lib/gitlab/database/load_balancing/session.rb', line 22

def self.without_sticky_writes(&block)
  current.ignore_writes(&block)
end

Instance Method Details

#fallback_to_replicas_for_ambiguous_queries(&blk) ⇒ Object

Indicate that the ambiguous SQL statements from anywhere inside this block should use a replica. The ambiguous statements include:

  • Transactions.

  • Custom queries (via exec_query, execute, etc.)

  • In-flight connection configuration change (SET LOCAL statement_timeout = 5000)

This is a weak enforcement. This helper incorporates well with primary stickiness:

  • If the queries are about to write

  • The current session already performed writes

  • It prefers to use primary, aka, use_primary or use_primary! were called



92
93
94
95
96
97
98
# File 'lib/gitlab/database/load_balancing/session.rb', line 92

def fallback_to_replicas_for_ambiguous_queries(&blk)
  previous_flag = @fallback_to_replicas_for_ambiguous_queries
  @fallback_to_replicas_for_ambiguous_queries = true
  yield
ensure
  @fallback_to_replicas_for_ambiguous_queries = previous_flag
end

#fallback_to_replicas_for_ambiguous_queries?Boolean

Returns:

  • (Boolean)


100
101
102
# File 'lib/gitlab/database/load_balancing/session.rb', line 100

def fallback_to_replicas_for_ambiguous_queries?
  @fallback_to_replicas_for_ambiguous_queries == true && !use_primary? && !performed_write?
end

#ignore_writes(&block) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/gitlab/database/load_balancing/session.rb', line 52

def ignore_writes(&block)
  @ignore_writes = true

  yield
ensure
  @ignore_writes = false
end

#performed_write?Boolean

Returns:

  • (Boolean)


112
113
114
# File 'lib/gitlab/database/load_balancing/session.rb', line 112

def performed_write?
  @performed_write
end

#use_primary(&blk) ⇒ Object



44
45
46
47
48
49
50
# File 'lib/gitlab/database/load_balancing/session.rb', line 44

def use_primary(&blk)
  used_primary = @use_primary
  @use_primary = true
  yield
ensure
  @use_primary = used_primary || @performed_write
end

#use_primary!Object



40
41
42
# File 'lib/gitlab/database/load_balancing/session.rb', line 40

def use_primary!
  @use_primary = true
end

#use_primary?Boolean Also known as: using_primary?

Returns:

  • (Boolean)


34
35
36
# File 'lib/gitlab/database/load_balancing/session.rb', line 34

def use_primary?
  @use_primary
end

#use_replicas_for_read_queries(&blk) ⇒ Object

Indicates that the read SQL statements from anywhere inside this blocks should use a replica, regardless of the current primary stickiness or whether a write query is already performed in the current session. This interface is reserved mostly for performance purpose. This is a good tool to push expensive queries, which can tolerate the replica lags, to the replicas.

Write and ambiguous queries inside this block are still handled by the primary.



69
70
71
72
73
74
75
# File 'lib/gitlab/database/load_balancing/session.rb', line 69

def use_replicas_for_read_queries(&blk)
  previous_flag = @use_replicas_for_read_queries
  @use_replicas_for_read_queries = true
  yield
ensure
  @use_replicas_for_read_queries = previous_flag
end

#use_replicas_for_read_queries?Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/gitlab/database/load_balancing/session.rb', line 77

def use_replicas_for_read_queries?
  @use_replicas_for_read_queries == true
end

#write!Object



104
105
106
107
108
109
110
# File 'lib/gitlab/database/load_balancing/session.rb', line 104

def write!
  @performed_write = true

  return if @ignore_writes

  use_primary!
end