22
22
from tenacity import RetryError , Retrying , stop_after_delay , wait_fixed
23
23
24
24
from connector import MySQLConnector # isort: skip
25
+ from literals import (
26
+ CONTINUOUS_WRITE_TABLE_NAME ,
27
+ DATABASE_NAME ,
28
+ DATABASE_RELATION ,
29
+ LEGACY_MYSQL_RELATION ,
30
+ PEER ,
31
+ PROC_PID_KEY ,
32
+ RANDOM_VALUE_KEY ,
33
+ RANDOM_VALUE_TABLE_NAME ,
34
+ )
35
+ from relations .legacy_mysql import LegacyMySQL
25
36
26
37
logger = logging .getLogger (__name__ )
27
38
28
- CONTINUOUS_WRITE_TABLE_NAME = "data"
29
- DATABASE_NAME = "continuous_writes_database"
30
- DATABASE_RELATION = "database"
31
- PEER = "application-peers"
32
- PROC_PID_KEY = "proc-pid"
33
- RANDOM_VALUE_KEY = "inserted_value"
34
- RANDOM_VALUE_TABLE_NAME = "random_data"
35
-
36
39
37
40
class MySQLTestApplication (CharmBase ):
38
41
"""Application charm that continuously writes to MySQL."""
@@ -42,7 +45,9 @@ def __init__(self, *args):
42
45
43
46
# Charm events
44
47
self .framework .observe (self .on .start , self ._on_start )
48
+ self .framework .observe (self .on [PEER ].relation_changed , self ._on_peer_relation_changed )
45
49
50
+ # Action handlers
46
51
self .framework .observe (
47
52
getattr (self .on , "clear_continuous_writes_action" ),
48
53
self ._on_clear_continuous_writes_action ,
@@ -79,6 +84,11 @@ def __init__(self, *args):
79
84
self .framework .observe (
80
85
self .on [DATABASE_RELATION ].relation_broken , self ._on_relation_broken
81
86
)
87
+ self .framework .observe (
88
+ self .on [LEGACY_MYSQL_RELATION ].relation_broken , self ._on_relation_broken
89
+ )
90
+ # Legacy MySQL/MariaDB Handler
91
+ self .legacy_mysql = LegacyMySQL (self )
82
92
83
93
# ==============
84
94
# Properties
@@ -108,13 +118,22 @@ def unit_peer_data(self) -> Dict:
108
118
@property
109
119
def _database_config (self ):
110
120
"""Returns the database config to use to connect to the MySQL cluster."""
111
- data = list (self .database .fetch_relation_data ().values ())[0 ]
112
-
113
- username , password , endpoints = (
114
- data .get ("username" ),
115
- data .get ("password" ),
116
- data .get ("endpoints" ),
117
- )
121
+ # identify the database relation
122
+ if self .model .get_relation (DATABASE_RELATION ):
123
+ data = list (self .database .fetch_relation_data ().values ())[0 ]
124
+
125
+ username , password , endpoints = (
126
+ data .get ("username" ),
127
+ data .get ("password" ),
128
+ data .get ("endpoints" ),
129
+ )
130
+ elif self .model .get_relation (LEGACY_MYSQL_RELATION ):
131
+ username = self .app_peer_data .get (f"{ LEGACY_MYSQL_RELATION } -user" )
132
+ password = self .app_peer_data .get (f"{ LEGACY_MYSQL_RELATION } -password" )
133
+ endpoints = self .app_peer_data .get (f"{ LEGACY_MYSQL_RELATION } -host" )
134
+ endpoints = f"{ endpoints } :3306"
135
+ else :
136
+ return {}
118
137
if None in [username , password , endpoints ]:
119
138
return {}
120
139
@@ -168,9 +187,6 @@ def _start_continuous_writes(self, starting_number: int) -> None:
168
187
169
188
def _stop_continuous_writes (self ) -> Optional [int ]:
170
189
"""Stop continuous writes to the MySQL cluster and return the last written value."""
171
- if not self ._database_config :
172
- return None
173
-
174
190
if not self .unit_peer_data .get (PROC_PID_KEY ):
175
191
return None
176
192
@@ -193,7 +209,7 @@ def _stop_continuous_writes(self) -> Optional[int]:
193
209
return last_written_value
194
210
195
211
def _max_written_value (self ) -> int :
196
- """Return the count of rows in the continuous writes table."""
212
+ """Return the max value in the continuous writes table."""
197
213
if not self ._database_config :
198
214
return - 1
199
215
@@ -203,7 +219,7 @@ def _max_written_value(self) -> int:
203
219
)
204
220
return cursor .fetchone ()[0 ]
205
221
206
- def _create_test_table (self , cursor ) -> None :
222
+ def _create_random_value_table (self , cursor ) -> None :
207
223
"""Create a test table in the database."""
208
224
cursor .execute (
209
225
(
@@ -214,7 +230,7 @@ def _create_test_table(self, cursor) -> None:
214
230
)
215
231
)
216
232
217
- def _insert_test_data (self , cursor , random_value : str ) -> None :
233
+ def _insert_random_value (self , cursor , random_value : str ) -> None :
218
234
"""Insert the provided random value into the test table in the database."""
219
235
cursor .execute (f"INSERT INTO `{ RANDOM_VALUE_TABLE_NAME } `(data) VALUES('{ random_value } ')" )
220
236
@@ -232,9 +248,9 @@ def _write_random_value(self) -> str:
232
248
for attempt in Retrying (stop = stop_after_delay (60 ), wait = wait_fixed (5 )):
233
249
with attempt :
234
250
with MySQLConnector (self ._database_config ) as cursor :
235
- self ._create_test_table (cursor )
251
+ self ._create_random_value_table (cursor )
236
252
random_value = self ._generate_random_values (10 )
237
- self ._insert_test_data (cursor , random_value )
253
+ self ._insert_random_value (cursor , random_value )
238
254
except RetryError :
239
255
logger .exception ("Unable to write to the database" )
240
256
return random_value
@@ -248,8 +264,11 @@ def _write_random_value(self) -> str:
248
264
# ==============
249
265
def _on_start (self , _ ) -> None :
250
266
"""Handle the start event."""
251
- self .unit .set_workload_version ("0.0.1" )
252
- self .unit .status = WaitingStatus ()
267
+ self .unit .set_workload_version ("0.0.2" )
268
+ if self ._database_config :
269
+ self .unit .status = ActiveStatus ()
270
+ else :
271
+ self .unit .status = WaitingStatus ()
253
272
254
273
def _on_clear_continuous_writes_action (self , _ ) -> None :
255
274
"""Handle the clear continuous writes action event."""
@@ -281,20 +300,32 @@ def _on_database_created(self, _) -> None:
281
300
"""Handle the database created event."""
282
301
if not self ._database_config :
283
302
return
284
-
285
- self ._start_continuous_writes (1 )
286
- value = self ._write_random_value ()
287
303
if self .unit .is_leader ():
288
- self .app_peer_data [RANDOM_VALUE_KEY ] = value
289
- self .unit .status = ActiveStatus ()
304
+ self .app_peer_data ["database-start" ] = "true"
290
305
291
306
def _on_endpoints_changed (self , _ ) -> None :
292
307
"""Handle the database endpoints changed event."""
293
308
count = self ._max_written_value ()
294
309
self ._start_continuous_writes (count + 1 )
295
310
311
+ def _on_peer_relation_changed (self , _ ) -> None :
312
+ """Handle common post database estabilshed tasks."""
313
+ if self .app_peer_data .get ("database-start" ) == "true" :
314
+ self ._start_continuous_writes (1 )
315
+
316
+ if self .unit .is_leader ():
317
+ value = self ._write_random_value ()
318
+ self .app_peer_data [RANDOM_VALUE_KEY ] = value
319
+ # flag should be picked up just once
320
+ self .app_peer_data ["database-start" ] = "done"
321
+
322
+ self .unit .status = ActiveStatus ()
323
+
296
324
def _on_relation_broken (self , _ ) -> None :
297
325
"""Handle the database relation broken event."""
326
+ self ._stop_continuous_writes ()
327
+ if self .unit .is_leader ():
328
+ self .app_peer_data .pop ("database-start" , None )
298
329
self .unit .status = WaitingStatus ()
299
330
300
331
def _get_inserted_data (self , event : ActionEvent ) -> None :
0 commit comments