Skip to content

Commit b22af81

Browse files
Revert "put back transactions, fix error messages"
This reverts commit b5afc26.
1 parent 41a9e52 commit b22af81

9 files changed

+84
-171
lines changed

include/ssod/database.h

+5-72
Original file line numberDiff line numberDiff line change
@@ -41,30 +41,19 @@ namespace db {
4141
* and push_back().
4242
*/
4343
struct resultset {
44-
4544
/**
4645
* Row values
4746
*/
4847
std::vector<row> rows;
49-
5048
/**
5149
* Error message of last query or an empty string on success
5250
*/
5351
std::string error;
54-
5552
/**
5653
* Number of affected rows, if an UPDATE, DELETE, INSERT
5754
*/
5855
size_t affected_rows{};
5956

60-
/**
61-
* Returns true if the query succeeded
62-
* @return true if no error
63-
*/
64-
[[nodiscard]] inline bool ok() const {
65-
return error.empty();
66-
}
67-
6857
/**
6958
* Get a row by index
7059
* @param index row to retrieve
@@ -76,7 +65,7 @@ namespace db {
7665

7766
/**
7867
* Get a row by index with range checking
79-
* @param index row to retrieve
68+
* @param index row to rerieve
8069
* @return row
8170
*/
8271
[[nodiscard]] inline const row& at(size_t index) const {
@@ -117,27 +106,16 @@ namespace db {
117106
return rows.end();
118107
}
119108

120-
/**
121-
* True if the recordset is empty
122-
* @return true if empty
123-
*/
124109
[[nodiscard]] inline bool empty() const {
125110
return rows.empty();
126111
}
127112

128-
/**
129-
* Number of rows in the recordset
130-
* @return row count
131-
*/
132113
[[nodiscard]] inline size_t size() const {
133114
return rows.size();
134115
}
135116
};
136117

137-
/**
138-
* @brief A callback which happens when an asynchronous SQL query is completed
139-
*/
140-
using sql_query_callback = std::function<void(const resultset&)>;
118+
141119

142120
/**
143121
* @brief Possible parameter types for SQL parameters
@@ -201,24 +179,6 @@ namespace db {
201179
*/
202180
resultset query(const std::string &format, const paramlist &parameters = {});
203181

204-
/**
205-
* @brief Run a mysql query asynchronously, with automatic escaping of parameters
206-
* to prevent SQL injection. Call the callback on completion
207-
*
208-
* @param format Format string, where each parameter should be indicated by a ? symbol
209-
* @param parameters Parameters to prepare into the query in place of the ?'s
210-
* @param cb Callback to call on completion of the query. The callback will be passed
211-
* the resultset as its parameter.
212-
*
213-
* The parameters given should be a vector of strings. You can instantiate this using "{}".
214-
* The queries are cached as prepared statements and therefore do not need quote symbols
215-
* to be placed around parameters in the query. These will be automatically added if required.
216-
*
217-
* @note If you can you should use co_query instead to avoid callback hell. co_query uses this
218-
* internally, wrapping it with dpp::async<>.
219-
*/
220-
void query_callback(const std::string &format, const paramlist &parameters, const sql_query_callback& cb);
221-
222182
#ifdef DPP_CORO
223183
/**
224184
* @brief Run a mysql query, with automatic escaping of parameters to prevent SQL injection.
@@ -269,18 +229,16 @@ namespace db {
269229
*
270230
* @note This value is by any db::query() call. Take a copy!
271231
* @return size_t Number of affected rows
272-
* @deprecated This is not coroutine-safe and you should use resultset::affected_rows instead
273232
*/
274-
[[deprecated("Use resultset::affected_rows instead")]] size_t affected_rows();
233+
size_t affected_rows();
275234

276235
/**
277236
* @brief Returns the last error string.
278237
*
279238
* @note This value is by any db::query() call. Take a copy!
280239
* @return const std::string& Error mesage
281-
* @deprecated This is not coroutine-safe and you should use resultset::error instead
282240
*/
283-
[[deprecated("Use resultset::error instead")]] const std::string& error();
241+
const std::string& error();
284242

285243
/**
286244
* @brief Returns the size of the query cache
@@ -309,39 +267,14 @@ namespace db {
309267
* will be forced to wait.
310268
*
311269
* @param closure The transactional code to execute.
312-
* @param callback Callback to call when the transaction completes
313270
*
314271
* @note The closure should only ever execute queries using db::query(),
315272
* it should NOT use async queries/co_query() as these cannot be executed
316273
* atomically.
317274
* Returning false from the closure, or throwing any exception at all
318275
* will roll back the transaction, else it will be committed when the
319276
* closure ends.
320-
* @warning The coroutine will execute asynchronously in a different thread.
321-
* You should use the callback to be notified when it completes. The resultset
322-
* passed as the parameter will be empty.
323277
*/
324-
void transaction(std::function<bool()> closure, sql_query_callback callback = {});
278+
void transaction(std::function<bool()> closure);
325279

326-
#ifdef DPP_CORO
327-
/**
328-
* @brief Start an SQL transaction in a coroutine that can be awaited.
329-
* SQL transactions are atomic in nature, ALL other queries will be forced
330-
* to wait. The transaction will be inserted into the queue to run as one atomic
331-
* operation, meaning that db::co_query cannot disrupt it or insert queries in
332-
* the middle of it, and db::query function calls that are not within the closure
333-
* will be forced to wait.
334-
*
335-
* @param closure The transactional code to execute.
336-
* @return Awaitable, returns an empty resultset on completion of transaction
337-
*
338-
* @note The closure should only ever execute queries using db::query(),
339-
* it should NOT use async queries/co_query() as these cannot be executed
340-
* atomically.
341-
* Returning false from the closure, or throwing any exception at all
342-
* will roll back the transaction, else it will be committed when the
343-
* closure ends.
344-
*/
345-
dpp::async<resultset> co_transaction(std::function<bool()> closure);
346-
#endif
347280
};

include/ssod/game_player.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ struct player {
314314
long max_silver();
315315
long max_mana();
316316
long max_rations();
317-
long max_crits() const;
317+
long max_crits();
318318

319319
void tick_mana();
320320

src/campfire.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ dpp::task<void> campfire(const dpp::interaction_create_t& event, player p) {
216216
event.reply(event.command.type == dpp::it_application_command ? dpp::ir_channel_message_with_source : dpp::ir_update_message, m.set_flags(dpp::m_ephemeral), [event, &bot, m](const auto& cc) {
217217
if (cc.is_error()) {
218218
bot.log(dpp::ll_error, "Internal error displaying campfire:\n```json\n" + cc.http_info.body + "\n```\nMessage:\n```json\n" + m.build_json() + "\n```");
219-
event.reply(dpp::message("Internal error displaying campfire:\nPlease report to developers via 'Get Help' button```").set_flags(dpp::m_ephemeral));
219+
event.reply(dpp::message("Internal error displaying campfire:\n```json\n" + cc.http_info.body + "\n```\nMessage:\n```json\n" + m.build_json() + "\n```").set_flags(dpp::m_ephemeral));
220220
}
221221
});
222222
}

src/combat.cpp

+35-41
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ dpp::task<void> continue_pvp_combat(const dpp::interaction_create_t& event, play
394394
event.reply(event.command.type == dpp::it_component_button ? dpp::ir_update_message : dpp::ir_channel_message_with_source, m.set_flags(dpp::m_ephemeral), [event, m, p](const auto& cc) {
395395
if (cc.is_error()) {
396396
//bot.log(dpp::ll_error, "Internal error displaying PvP combat location " + std::to_string(p.paragraph) + ": " + cc.http_info.body);
397-
event.reply(dpp::message("Internal error displaying Pvp combat location " + std::to_string(p.paragraph) + ":\nPlease report to developers via 'Get Help' button").set_flags(dpp::m_ephemeral));
397+
event.reply(dpp::message("Internal error displaying Pvp combat location " + std::to_string(p.paragraph) + ":\n```json\n" + cc.http_info.body + "\n```\nMessage:\n```json\n" + m.build_json() + "\n```").set_flags(dpp::m_ephemeral));
398398
}
399399
});
400400
co_return;
@@ -659,30 +659,27 @@ dpp::task<void> continue_combat(const dpp::interaction_create_t& event, player p
659659

660660
output << "__" << tr("COMBAT", event) << "__: **" << p.name << "** vs. **" << p.combatant.name << "**\n\n";
661661

662+
auto r = co_await db::co_query("SELECT * FROM criticals WHERE user_id = ?", {event.command.usr.id});
662663
long banked{0};
663664
bool critical{};
664-
co_await db::co_transaction([event, &output, &p, &critical, &banked]() -> bool {
665-
auto r = db::query("SELECT * FROM criticals WHERE user_id = ?", {event.command.usr.id});
666-
if (!r.empty()) {
667-
long counter = atol(r[0].at("critical_counter"));
668-
banked = atol(r[0].at("banked_criticals"));
669-
if (banked > 0 && p.next_crit) {
670-
db::query("UPDATE criticals SET banked_criticals = banked_criticals - 1 WHERE user_id = ?", {event.command.usr.id});
671-
critical = true;
672-
p.next_crit = false;
673-
banked--;
674-
}
675-
long next = 1000 + (p.get_level() * 4);
676-
int percent = (double)counter / (double)next * 100.0f;
677-
output << tr("CRITICAL_METER", event) << ": ";
678-
for (int x = 0; x < 100; x += 10) {
679-
output << (x < percent ? sprite::bar_green.get_mention() : sprite::bar_red.get_mention());
680-
}
681-
output << " (" + std::to_string(percent) + "%)\n";
682-
output << tr("CRITICALS", event) << ": " << std::max(banked, 0L) << "/" << p.max_crits();
665+
if (!r.empty()) {
666+
long counter = atol(r[0].at("critical_counter"));
667+
banked = atol(r[0].at("banked_criticals"));
668+
if (banked > 0 && p.next_crit) {
669+
co_await db::co_query("UPDATE criticals SET banked_criticals = banked_criticals - 1 WHERE user_id = ?", {event.command.usr.id});
670+
critical = true;
671+
p.next_crit = false;
672+
banked--;
683673
}
684-
return true;
685-
});
674+
long next = 1000 + (p.get_level() * 4);
675+
int percent = (double)counter / (double)next * 100.0f;
676+
output << tr("CRITICAL_METER", event) << ": ";
677+
for (int x = 0; x < 100; x += 10) {
678+
output << (x < percent ? sprite::bar_green.get_mention() : sprite::bar_red.get_mention());
679+
}
680+
output << " (" + std::to_string(percent) + "%)\n";
681+
output << tr("CRITICALS", event) << ": " << std::max(banked, 0L) << "/" << p.max_crits();
682+
}
686683

687684
if (EStamina <= 0) {
688685
output << tr("HES_DEAD_JIM", event) << "\n\n";
@@ -758,25 +755,22 @@ dpp::task<void> continue_combat(const dpp::interaction_create_t& event, player p
758755
} else {
759756
output << "__**" << tr("YOUHITENEMY", event) << "**__.";
760757

761-
co_await db::co_transaction([p, event]() -> bool {
762-
/* If you hit enemy, critical meter ticks up based on your luck.
763-
* If critical meter reaches max, you gain a critical hit, that you
764-
* can spend on an overwhelming attack.
765-
*/
766-
db::query("INSERT INTO criticals (user_id, critical_counter, banked_criticals) VALUES(?,1,0) ON DUPLICATE KEY UPDATE critical_counter = critical_counter + ?", {event.command.usr.id, p.luck + 1});
767-
auto r = db::query("SELECT * FROM criticals WHERE user_id = ?", {event.command.usr.id});
768-
long counter = atol(r[0].at("critical_counter"));
769-
if (counter > 1000 + (p.get_level() * 4)) {
770-
/* User gains a new banked critical */
771-
long new_banked = atol(r[0].at("banked_criticals")) + 1;
772-
if (new_banked <= p.max_crits()) {
773-
db::query("UPDATE criticals SET critical_counter = 0, banked_criticals = ? WHERE user_id = ?", {new_banked, event.command.usr.id});
774-
} else {
775-
db::query("UPDATE criticals SET critical_counter = 0 WHERE user_id = ?", {event.command.usr.id});
776-
}
758+
/* If you hit enemy, critical meter ticks up based on your luck.
759+
* If critical meter reaches max, you gain a critical hit, that you
760+
* can spend on an overwhelming attack.
761+
*/
762+
co_await db::co_query("INSERT INTO criticals (user_id, critical_counter, banked_criticals) VALUES(?,1,0) ON DUPLICATE KEY UPDATE critical_counter = critical_counter + ?", {event.command.usr.id, p.luck + 1});
763+
auto r = co_await db::co_query("SELECT * FROM criticals WHERE user_id = ?", {event.command.usr.id});
764+
long counter = atol(r[0].at("critical_counter"));
765+
if (counter > 1000 + (p.get_level() * 4)) {
766+
/* User gains a new banked critical */
767+
long new_banked = atol(r[0].at("banked_criticals")) + 1;
768+
if (new_banked <= p.max_crits()) {
769+
co_await db::co_query("UPDATE criticals SET critical_counter = 0, banked_criticals = ? WHERE user_id = ?", {new_banked, event.command.usr.id});
770+
} else {
771+
co_await db::co_query("UPDATE criticals SET critical_counter = 0 WHERE user_id = ?", {event.command.usr.id});
777772
}
778-
return true;
779-
});
773+
}
780774

781775
if (EStance == DEFENSIVE) {
782776
output << tr("ATKBONUS", event);
@@ -1036,7 +1030,7 @@ dpp::task<void> continue_combat(const dpp::interaction_create_t& event, player p
10361030
event.reply(event.command.type == dpp::it_component_button ? dpp::ir_update_message : dpp::ir_channel_message_with_source, m.set_flags(dpp::m_ephemeral), [event, &bot, m, p](const auto& cc) {
10371031
if (cc.is_error()) {
10381032
bot.log(dpp::ll_error, "Internal error displaying PvE combat " + std::to_string(p.after_fragment) + " location " + std::to_string(p.paragraph) + ": " + cc.http_info.body + " -- " + m.build_json());
1039-
event.reply(dpp::message("Internal error displaying PvE combat " + std::to_string(p.after_fragment) + " location " + std::to_string(p.paragraph) + ":\nPlease report to developers via 'Get Help' button").set_flags(dpp::m_ephemeral));
1033+
event.reply(dpp::message("Internal error displaying PvE combat " + std::to_string(p.after_fragment) + " location " + std::to_string(p.paragraph) + ":\n```json\n" + cc.http_info.body + "\n```\nMessage:\n```json\n" + m.build_json() + "\n```").set_flags(dpp::m_ephemeral));
10401034
}
10411035
});
10421036

src/database.cpp

+15-16
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ namespace db {
108108
*/
109109
std::map<std::string, cached_query> cached_queries;
110110

111+
using sql_query_callback = std::function<void(const resultset&)>;
112+
111113
std::condition_variable sql_worker_cv;
112114

113115
/**
@@ -127,8 +129,10 @@ namespace db {
127129
const double expiry;
128130
};
129131

132+
#ifdef DPP_CORO
130133
std::queue<cached_query_results> sql_query_queue;
131134
std::mutex query_queue_mtx;
135+
#endif
132136

133137
template<class> inline constexpr bool always_false_v = false;
134138

@@ -216,6 +220,7 @@ namespace db {
216220
return unsafe_connect(host, user, pass, db, port, socket);
217221
}
218222

223+
#ifdef DPP_CORO
219224
void query_callback(const std::string &format, const paramlist &parameters, const sql_query_callback& cb) {
220225
{
221226
std::unique_lock<std::mutex> queue_lock(query_queue_mtx);
@@ -224,7 +229,6 @@ namespace db {
224229
sql_worker_cv.notify_one();
225230
}
226231

227-
#ifdef DPP_CORO
228232
dpp::async<resultset> co_query(const std::string &format, const paramlist &parameters) {
229233
return dpp::async<resultset>{ [format, parameters] <typename C> (C &&cc) { return query_callback(format, parameters, std::forward<C>(cc)); }};
230234
}
@@ -237,6 +241,7 @@ namespace db {
237241
creator->log(dpp::ll_critical, fmt::format("Database connection error connecting to {}: {}", dbconf["database"], mysql_error(&connection)));
238242
exit(2);
239243
}
244+
#ifdef DPP_CORO
240245
std::thread([&]() {
241246
dpp::utility::set_thread_name("sql/coro");
242247
while (true) {
@@ -252,6 +257,12 @@ namespace db {
252257
qr = std::move(sql_query_queue.front());
253258
sql_query_queue.pop();
254259
}
260+
if (!qr.format.empty()) {
261+
auto results = query(qr.format, qr.parameters);
262+
if (qr.callback) {
263+
qr.callback(results);
264+
}
265+
}
255266
/**
256267
* If a transaction is waiting to be executed, fit it atomically into
257268
* the queue here. The holds_transaction_lock is a thread_local variable
@@ -266,15 +277,9 @@ namespace db {
266277
holds_transaction_lock = false;
267278
transaction_function = {};
268279
}
269-
resultset results{};
270-
if (!qr.format.empty()) {
271-
results = query(qr.format, qr.parameters);
272-
}
273-
if (qr.callback) {
274-
qr.callback(results);
275-
}
276280
}
277281
}).detach();
282+
#endif
278283
creator->log(dpp::ll_info, fmt::format("Connected to database: {}", dbconf["database"]));
279284
}
280285

@@ -304,7 +309,7 @@ namespace db {
304309
return raw_query("ROLLBACK");
305310
}
306311

307-
void transaction(std::function<bool()> closure, sql_query_callback callback) {
312+
void transaction(std::function<bool()> closure) {
308313

309314
if (transaction_in_progress) {
310315
throw std::runtime_error("Transaction already in progress");
@@ -343,15 +348,9 @@ namespace db {
343348
* query to signal the condition variable and make the SQL queue advance.
344349
*/
345350
transaction_in_progress = true;
346-
query_callback("", {}, callback);
351+
query_callback("", {}, [](auto){});
347352
}
348353

349-
#ifdef DPP_CORO
350-
dpp::async<resultset> co_transaction(std::function<bool()> closure) {
351-
return dpp::async<resultset>{ [closure] <typename C> (C &&cc) { return transaction(closure, std::forward<C>(cc)); }};
352-
}
353-
#endif
354-
355354
bool close() {
356355
std::lock_guard<std::mutex> db_lock(db_mutex);
357356
mysql_close(&connection);

0 commit comments

Comments
 (0)