Class: ChatSDK::State::Mysql

Inherits:
Base
  • Object
show all
Defined in:
lib/chat_sdk/state/mysql.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url: nil, connection: nil, key_prefix: "chat_sdk", auto_migrate: true) ⇒ Mysql

Returns a new instance of Mysql.



10
11
12
13
14
# File 'lib/chat_sdk/state/mysql.rb', line 10

def initialize(url: nil, connection: nil, key_prefix: "chat_sdk", auto_migrate: true)
  @conn = connection || connect(url || ENV["MYSQL_URL"] || ENV["DATABASE_URL"] || "mysql2://root@localhost/chat_sdk_dev")
  @key_prefix = key_prefix
  ensure_tables if auto_migrate
end

Instance Attribute Details

#connObject (readonly)

Returns the value of attribute conn.



16
17
18
# File 'lib/chat_sdk/state/mysql.rb', line 16

def conn
  @conn
end

Instance Method Details

#acquire_lock(key, owner:, ttl:) ⇒ Object

Locks



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/chat_sdk/state/mysql.rb', line 44

def acquire_lock(key, owner:, ttl:)
  ttl_seconds = ttl.to_f
  del_stmt = @conn.prepare(
    "DELETE FROM chat_sdk_locks WHERE key_prefix = ? AND lock_key = ? AND expires_at < NOW()"
  )
  del_stmt.execute(@key_prefix, key)
  ins_stmt = @conn.prepare(
    "INSERT IGNORE INTO chat_sdk_locks (key_prefix, lock_key, owner, expires_at) " \
    "VALUES (?, ?, ?, DATE_ADD(NOW(), INTERVAL #{ttl_seconds} SECOND))"
  )
  ins_stmt.execute(@key_prefix, key, owner)
  @conn.affected_rows > 0
end

#cleanup_expiredObject



152
153
154
155
156
157
158
159
160
161
# File 'lib/chat_sdk/state/mysql.rb', line 152

def cleanup_expired
  s1 = @conn.prepare(
    "DELETE FROM chat_sdk_cache WHERE key_prefix = ? AND expires_at IS NOT NULL AND expires_at < NOW()"
  )
  s1.execute(@key_prefix)
  s2 = @conn.prepare(
    "DELETE FROM chat_sdk_locks WHERE key_prefix = ? AND expires_at < NOW()"
  )
  s2.execute(@key_prefix)
end

#clearObject

Cleanup



143
144
145
146
147
148
149
150
# File 'lib/chat_sdk/state/mysql.rb', line 143

def clear
  s1 = @conn.prepare("DELETE FROM chat_sdk_subscriptions WHERE key_prefix = ?")
  s1.execute(@key_prefix)
  s2 = @conn.prepare("DELETE FROM chat_sdk_locks WHERE key_prefix = ?")
  s2.execute(@key_prefix)
  s3 = @conn.prepare("DELETE FROM chat_sdk_cache WHERE key_prefix = ?")
  s3.execute(@key_prefix)
end

#delete(key) ⇒ Object



109
110
111
112
113
114
115
116
117
118
# File 'lib/chat_sdk/state/mysql.rb', line 109

def delete(key)
  stmt1 = @conn.prepare(
    "DELETE FROM chat_sdk_cache WHERE key_prefix = ? AND cache_key = ?"
  )
  stmt1.execute(@key_prefix, key)
  stmt2 = @conn.prepare(
    "DELETE FROM chat_sdk_locks WHERE key_prefix = ? AND lock_key = ?"
  )
  stmt2.execute(@key_prefix, key)
end

#force_lock(key, owner:, ttl:) ⇒ Object



66
67
68
69
70
71
72
73
74
75
# File 'lib/chat_sdk/state/mysql.rb', line 66

def force_lock(key, owner:, ttl:)
  ttl_seconds = ttl.to_f
  stmt = @conn.prepare(
    "INSERT INTO chat_sdk_locks (key_prefix, lock_key, owner, expires_at) " \
    "VALUES (?, ?, ?, DATE_ADD(NOW(), INTERVAL #{ttl_seconds} SECOND)) " \
    "ON DUPLICATE KEY UPDATE owner = VALUES(owner), expires_at = VALUES(expires_at)"
  )
  stmt.execute(@key_prefix, key, owner)
  true
end

#get(key) ⇒ Object

Key-value store



79
80
81
82
83
84
85
86
87
88
# File 'lib/chat_sdk/state/mysql.rb', line 79

def get(key)
  stmt = @conn.prepare(
    "SELECT value FROM chat_sdk_cache WHERE key_prefix = ? AND cache_key = ? AND (expires_at IS NULL OR expires_at > NOW())"
  )
  result = stmt.execute(@key_prefix, key)
  row = result.first
  return JSON.parse(row["value"]) if row

  nil
end

#release_lock(key, owner:) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/chat_sdk/state/mysql.rb', line 58

def release_lock(key, owner:)
  stmt = @conn.prepare(
    "DELETE FROM chat_sdk_locks WHERE key_prefix = ? AND lock_key = ? AND owner = ?"
  )
  stmt.execute(@key_prefix, key, owner)
  @conn.affected_rows > 0
end

#set(key, value, ttl: nil) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/chat_sdk/state/mysql.rb', line 90

def set(key, value, ttl: nil)
  serialized = JSON.generate(value)
  stmt = if ttl
    @conn.prepare(
      "INSERT INTO chat_sdk_cache (key_prefix, cache_key, value, expires_at) " \
      "VALUES (?, ?, ?, DATE_ADD(NOW(), INTERVAL #{ttl.to_f} SECOND)) " \
      "ON DUPLICATE KEY UPDATE value = VALUES(value), expires_at = VALUES(expires_at)"
    )
  else
    @conn.prepare(
      "INSERT INTO chat_sdk_cache (key_prefix, cache_key, value, expires_at) " \
      "VALUES (?, ?, ?, NULL) " \
      "ON DUPLICATE KEY UPDATE value = VALUES(value), expires_at = VALUES(expires_at)"
    )
  end
  stmt.execute(@key_prefix, key, serialized)
  value
end

#set_if_absent(key, value, ttl: nil) ⇒ Object



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

def set_if_absent(key, value, ttl: nil)
  serialized = JSON.generate(value)
  del_stmt = @conn.prepare(
    "DELETE FROM chat_sdk_cache WHERE key_prefix = ? AND cache_key = ? AND expires_at IS NOT NULL AND expires_at < NOW()"
  )
  del_stmt.execute(@key_prefix, key)
  stmt = if ttl
    @conn.prepare(
      "INSERT IGNORE INTO chat_sdk_cache (key_prefix, cache_key, value, expires_at) " \
      "VALUES (?, ?, ?, DATE_ADD(NOW(), INTERVAL #{ttl.to_f} SECOND))"
    )
  else
    @conn.prepare(
      "INSERT IGNORE INTO chat_sdk_cache (key_prefix, cache_key, value, expires_at) " \
      "VALUES (?, ?, ?, NULL)"
    )
  end
  stmt.execute(@key_prefix, key, serialized)
  @conn.affected_rows > 0
end

#subscribe(thread_id) ⇒ Object

Subscriptions



20
21
22
23
24
25
# File 'lib/chat_sdk/state/mysql.rb', line 20

def subscribe(thread_id)
  stmt = @conn.prepare(
    "INSERT IGNORE INTO chat_sdk_subscriptions (key_prefix, thread_id) VALUES (?, ?)"
  )
  stmt.execute(@key_prefix, thread_id)
end

#subscribed?(thread_id) ⇒ Boolean

Returns:

  • (Boolean)


34
35
36
37
38
39
40
# File 'lib/chat_sdk/state/mysql.rb', line 34

def subscribed?(thread_id)
  stmt = @conn.prepare(
    "SELECT 1 FROM chat_sdk_subscriptions WHERE key_prefix = ? AND thread_id = ?"
  )
  result = stmt.execute(@key_prefix, thread_id)
  result.count > 0
end

#unsubscribe(thread_id) ⇒ Object



27
28
29
30
31
32
# File 'lib/chat_sdk/state/mysql.rb', line 27

def unsubscribe(thread_id)
  stmt = @conn.prepare(
    "DELETE FROM chat_sdk_subscriptions WHERE key_prefix = ? AND thread_id = ?"
  )
  stmt.execute(@key_prefix, thread_id)
end