-
Notifications
You must be signed in to change notification settings - Fork 7
/
cache.py
144 lines (119 loc) · 3.88 KB
/
cache.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#! /usr/bin/env python3
# -*- coding: utf-8; py-indent-offset: 4 -*-
#
# Author: Linuxfabrik GmbH, Zurich, Switzerland
# Contact: info (at) linuxfabrik (dot) ch
# https://www.linuxfabrik.ch/
# License: The Unlicense, see LICENSE file.
# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.rst
"""Simple Cache in the form of a Key-Value Store (KVS) like Redis, based on
SQLite, optionally supporting expiration of keys. No detailed error handling
here. If the cache does not work, we (currently) don't report the reason and
simply return `False`.
>>> cache.get('session-key')
False
>>> cache.set('session-key', '123abc', expire=time.now() + 5)
True
>>> cache.get('session-key')
u'123abc'
>>> time.sleep(6)
>>> cache.get('session-key')
False
"""
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
__version__ = '2023112901'
from . import time
from . import db_sqlite
def get(key, as_dict=False, path='', filename='linuxfabrik-monitoring-plugins-cache.db'):
"""Get the value of key. If the key does not exist, `False` is returned.
Parameters
----------
key : str
The search key.
Returns
-------
str or bool
The value that belongs to the key, `False` if not found or on
failure.
"""
success, conn = db_sqlite.connect(path=path, filename=filename)
if not success:
return False
success, result = db_sqlite.select(
conn,
sql='SELECT key, value, timestamp FROM cache WHERE key = :key;',
data={'key': key}, fetchone=True
)
if not success:
# error accessing or querying the cache
db_sqlite.close(conn)
return False
if not result or result is None:
# key not found
db_sqlite.close(conn)
return False
if result['timestamp'] != 0 and result['timestamp'] <= time.now():
# key was found, but timstamp was set and has expired:
# delete all expired keys and return false
success, result = db_sqlite.delete(
conn,
sql='DELETE FROM cache WHERE timestamp <= {};'.format(time.now())
)
success, result = db_sqlite.commit(conn)
db_sqlite.close(conn)
return False
# return the value
db_sqlite.close(conn)
if not as_dict:
# just return the value (as used to when for example using Redis)
return result['value']
# return all columns
return result
def set(key, value, expire=0, path='', filename='linuxfabrik-monitoring-plugins-cache.db'):
"""Set key to hold the string value.
Keys have to be unique. If the key already holds a value, it is
overwritten, including the expire timestamp in seconds.
Parameters
----------
key : str
The key.
value : str
The value. Always stored as string.
expire : int
Set the expire unix timestamp, in seconds. If 0 (default), key never
expires.
Returns
-------
bool
`True` on success, `False` on failure.
"""
success, conn = db_sqlite.connect(path=path, filename=filename)
if not success:
return False
definition = '''
key TEXT NOT NULL,
value TEXT NOT NULL,
timestamp INT NOT NULL
'''
success, result = db_sqlite.create_table(conn, definition, table='cache')
if not success:
db_sqlite.close(conn)
return False
success, result = db_sqlite.create_index(conn, column_list='key', table='cache', unique=True)
if not success:
db_sqlite.close(conn)
return False
data = {
'key': key,
'value': value,
'timestamp': expire,
}
success, result = db_sqlite.replace(conn, data, table='cache')
if not success:
db_sqlite.close(conn)
return False
success, result = db_sqlite.commit(conn)
db_sqlite.close(conn)
if not success:
return False
return True