Skip to content

Commit e2aca53

Browse files
committed
Make startup error report sending asynchronous to not block startup.
1 parent 26319fc commit e2aca53

File tree

7 files changed

+99
-58
lines changed

7 files changed

+99
-58
lines changed

Common/Cpp/Concurrency/ScheduledTaskRunner.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,43 @@ ScheduledTaskRunner::~ScheduledTaskRunner(){
2020
// ScheduledTaskRunner::cancel(nullptr);
2121
{
2222
std::lock_guard<std::mutex> lg(m_lock);
23+
// cout << "ScheduledTaskRunner: (Destructor - start): " << this << endl;
2324
m_stopped = true;
2425
m_cv.notify_all();
2526
}
2627
m_runner.reset();
28+
// cout << "ScheduledTaskRunner: (Destructor - end): " << this << endl;
2729
}
2830
ScheduledTaskRunner::ScheduledTaskRunner(AsyncDispatcher& dispatcher)
2931
: m_stopped(false)
3032
, m_runner(dispatcher.dispatch([this]{ thread_loop(); }))
31-
{}
33+
{
34+
// cout << "ScheduledTaskRunner: (Constructor): " << this << endl;
35+
}
3236
size_t ScheduledTaskRunner::size() const{
3337
std::lock_guard<std::mutex> lg(m_lock);
3438
return m_schedule.size();
3539
}
3640
WallClock ScheduledTaskRunner::next_event() const{
3741
std::lock_guard<std::mutex> lg(m_lock);
38-
if (m_schedule.empty()){
42+
if (m_stopped || m_schedule.empty()){
3943
return WallClock::max();
4044
}
4145
return m_schedule.begin()->first;
4246
}
4347
void ScheduledTaskRunner::add_event(WallClock time, std::function<void()> callback){
4448
std::lock_guard<std::mutex> lg(m_lock);
49+
if (m_stopped){
50+
return;
51+
}
4552
m_schedule.emplace(time, std::move(callback));
4653
m_cv.notify_all();
4754
}
4855
void ScheduledTaskRunner::add_event(std::chrono::milliseconds time_from_now, std::function<void()> callback){
4956
std::lock_guard<std::mutex> lg(m_lock);
57+
if (m_stopped){
58+
return;
59+
}
5060
m_schedule.emplace(current_time() + time_from_now, std::move(callback));
5161
m_cv.notify_all();
5262
}
@@ -62,6 +72,7 @@ bool ScheduledTaskRunner::cancel(std::exception_ptr exception) noexcept{
6272
#endif
6373
void ScheduledTaskRunner::thread_loop(){
6474
std::unique_lock<std::mutex> lg(m_lock);
75+
// cout << "ScheduledTaskRunner: (Starting thread loop): " << this << endl;
6576
// WallClock last_check_timestamp = current_time();
6677
while (!m_stopped){
6778
#if 0
@@ -71,7 +82,9 @@ void ScheduledTaskRunner::thread_loop(){
7182
#endif
7283

7384
if (m_schedule.empty()){
85+
// cout << "ScheduledTaskRunner: (Sleeping): " << this << endl;
7486
m_cv.wait(lg);
87+
// cout << "ScheduledTaskRunner: (Waking): " << this << endl;
7588
continue;
7689
}
7790

@@ -81,11 +94,15 @@ void ScheduledTaskRunner::thread_loop(){
8194
m_cv.wait_until(lg, item->first);
8295
continue;
8396
}
97+
// cout << "ScheduledTaskRunner: (task - start): " << this << endl;
8498
lg.unlock();
8599
item->second();
86100
lg.lock();
101+
// cout << "ScheduledTaskRunner: (task - end): " << this << endl;
87102
m_schedule.erase(item);
88103
}
104+
// cout << "ScheduledTaskRunner: (Clearing schedule): " << this << endl;
105+
m_schedule.clear();
89106
}
90107

91108

SerialPrograms/Source/CommonFramework/ErrorReports/ErrorReports.cpp

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
#include "Common/Cpp/PrettyPrint.h"
1111
#include "Common/Cpp/Json/JsonArray.h"
1212
#include "Common/Cpp/Json/JsonObject.h"
13+
#include "Common/Cpp/Concurrency/AsyncDispatcher.h"
1314
#include "CommonFramework/Globals.h"
1415
#include "CommonFramework/GlobalSettingsPanel.h"
16+
#include "CommonFramework/GlobalServices.h"
1517
#include "CommonFramework/Logging/Logger.h"
1618
#include "CommonFramework/Notifications/ProgramNotifications.h"
1719
#include "CommonFramework/Environment/Environment.h"
@@ -165,56 +167,63 @@ SendableErrorReport::SendableErrorReport(std::string directory)
165167
JsonValue json = load_json_file(m_directory + "Report.json");
166168
const JsonObject& obj = json.to_object_throw();
167169
m_timestamp = obj.get_string_throw("Timestamp");
168-
m_processor = obj.get_string_throw("Processor");
169-
m_program = obj.get_string_throw("Program");
170-
m_program_id = obj.get_string_throw("ProgramID");
171-
m_program_runtime_millis = obj.get_integer_throw("ElapsedTimeMillis");
172-
m_title = obj.get_string_throw("Title");
173-
{
174-
const JsonArray& messages = obj.get_array_throw("Messages");
175-
for (const JsonValue& message : messages){
176-
const JsonArray& item = message.to_array_throw();
177-
if (item.size() != 2){
178-
throw ParseException("Expected 2 values for message.");
170+
171+
// If we error from this point on, we'll just move it to the sent folder.
172+
try{
173+
m_processor = obj.get_string_throw("Processor");
174+
m_program = obj.get_string_throw("Program");
175+
m_program_id = obj.get_string_throw("ProgramID");
176+
m_program_runtime_millis = obj.get_integer_throw("ElapsedTimeMillis");
177+
m_title = obj.get_string_throw("Title");
178+
{
179+
const JsonArray& messages = obj.get_array_throw("Messages");
180+
for (const JsonValue& message : messages){
181+
const JsonArray& item = message.to_array_throw();
182+
if (item.size() != 2){
183+
throw ParseException("Expected 2 values for message.");
184+
}
185+
m_messages.emplace_back(
186+
item[0].to_string_throw(),
187+
item[1].to_string_throw()
188+
);
179189
}
180-
m_messages.emplace_back(
181-
item[0].to_string_throw(),
182-
item[1].to_string_throw()
183-
);
184190
}
185-
}
186-
{
187-
const std::string* image_name = obj.get_string("Screenshot");
188-
if (image_name){
189-
try{
190-
m_image_owner = ImageRGB32(m_directory + *image_name);
191-
m_image = m_image_owner;
192-
}catch (FileException&){}
191+
{
192+
const std::string* image_name = obj.get_string("Screenshot");
193+
if (image_name){
194+
try{
195+
m_image_owner = ImageRGB32(m_directory + *image_name);
196+
m_image = m_image_owner;
197+
}catch (FileException&){}
198+
}
193199
}
194-
}
195-
{
196-
const std::string* video_name = obj.get_string("Video");
197-
if (video_name){
198-
m_video_name = *video_name;
200+
{
201+
const std::string* video_name = obj.get_string("Video");
202+
if (video_name){
203+
m_video_name = *video_name;
204+
}
199205
}
200-
}
201-
{
202-
const std::string* dump_name = obj.get_string("Dump");
203-
if (dump_name){
204-
m_dump_name = *dump_name;
206+
{
207+
const std::string* dump_name = obj.get_string("Dump");
208+
if (dump_name){
209+
m_dump_name = *dump_name;
210+
}
205211
}
206-
}
207-
{
208-
const std::string* logs_name = obj.get_string("Logs");
209-
if (logs_name){
210-
m_logs_name = *logs_name;
212+
{
213+
const std::string* logs_name = obj.get_string("Logs");
214+
if (logs_name){
215+
m_logs_name = *logs_name;
216+
}
211217
}
212-
}
213-
{
214-
const JsonArray& files = obj.get_array_throw("Files");
215-
for (const JsonValue& file : files){
216-
m_files.emplace_back(file.to_string_throw());
218+
{
219+
const JsonArray& files = obj.get_array_throw("Files");
220+
for (const JsonValue& file : files){
221+
m_files.emplace_back(file.to_string_throw());
222+
}
217223
}
224+
}catch (...){
225+
move_to_sent();
226+
throw;
218227
}
219228
}
220229
void SendableErrorReport::add_file(std::string filename){
@@ -283,10 +292,15 @@ void SendableErrorReport::move_to_sent(){
283292
std::string new_directory = ERROR_PATH_SENT + "/" + m_timestamp + "/";
284293
// cout << "old: " << m_directory << endl;
285294
// cout << "new: " << new_directory << endl;
286-
QDir().rename(
295+
bool success = QDir().rename(
287296
QString::fromStdString(m_directory),
288297
QString::fromStdString(new_directory)
289298
);
299+
if (success){
300+
global_logger_tagged().log("Moved error report " + m_timestamp + ".");
301+
}else{
302+
global_logger_tagged().log("Unable to move error report " + m_timestamp + ".", COLOR_RED);
303+
}
290304
m_directory = std::move(new_directory);
291305
}
292306

@@ -311,6 +325,8 @@ std::vector<std::string> SendableErrorReport::get_pending_reports(){
311325
void send_reports(Logger& logger, const std::vector<std::string>& reports){
312326
for (const std::string& path : reports){
313327
try{
328+
// static int c = 0;
329+
// cout << "Sending... " << c++ << endl;
314330
SendableErrorReport report(path);
315331
report.send(logger);
316332
}catch (Exception& e){
@@ -320,23 +336,23 @@ void send_reports(Logger& logger, const std::vector<std::string>& reports){
320336
}
321337
}
322338
}
323-
void send_all_unsent_reports(Logger& logger, bool allow_prompt){
339+
std::unique_ptr<AsyncTask> send_all_unsent_reports(Logger& logger, bool allow_prompt){
324340
#ifdef PA_OFFICIAL
325341
ErrorReportSendMode mode = GlobalSettings::instance().ERROR_REPORTS->SEND_MODE;
326342
if (mode == ErrorReportSendMode::NEVER_SEND_ANYTHING){
327-
return;
343+
return nullptr;
328344
}
329345

330346
std::vector<std::string> reports = SendableErrorReport::get_pending_reports();
331347
global_logger_tagged().log("Found " + std::to_string(reports.size()) + " unsent error reports.", COLOR_PURPLE);
332348

333349
if (reports.empty()){
334-
return;
350+
return nullptr;
335351
}
336352

337353
if (mode == ErrorReportSendMode::PROMPT_WHEN_CONVENIENT){
338354
if (!allow_prompt){
339-
return;
355+
return nullptr;
340356
}
341357
QMessageBox box;
342358
QMessageBox::StandardButton button = box.information(
@@ -356,12 +372,15 @@ void send_all_unsent_reports(Logger& logger, bool allow_prompt){
356372
QMessageBox::StandardButton::Yes
357373
);
358374
if (button != QMessageBox::StandardButton::Yes){
359-
return;
375+
return nullptr;
360376
}
361377
}
362378

363379
global_logger_tagged().log("Attempting to send " + std::to_string(reports.size()) + " error reports.", COLOR_PURPLE);
364-
send_reports(global_logger_tagged(), reports);
380+
381+
return global_async_dispatcher().dispatch([reports = std::move(reports)]{
382+
send_reports(global_logger_tagged(), reports);
383+
});
365384

366385
#endif
367386
}

SerialPrograms/Source/CommonFramework/ErrorReports/ErrorReports.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
namespace PokemonAutomation{
2020

2121

22+
class AsyncTask;
2223
class ConsoleHandle;
2324

2425

@@ -100,7 +101,7 @@ class SendableErrorReport{
100101

101102

102103
void send_reports(Logger& logger, const std::vector<std::string>& reports);
103-
void send_all_unsent_reports(Logger& logger, bool allow_prompt);
104+
std::unique_ptr<AsyncTask> send_all_unsent_reports(Logger& logger, bool allow_prompt);
104105

105106

106107
void report_error(

SerialPrograms/Source/CommonFramework/GlobalServices.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
*
55
*/
66

7-
//#include "Common/Cpp/Concurrency/ScheduledTaskRunner.h"
7+
#include "Common/Cpp/Concurrency/ScheduledTaskRunner.h"
88
#include "Common/Cpp/Concurrency/Watchdog.h"
99
#include "GlobalServices.h"
1010

1111
namespace PokemonAutomation{
1212

1313

14-
#if 0
1514
AsyncDispatcher& global_async_dispatcher(){
1615
static AsyncDispatcher dispatcher(nullptr, 1);
1716
return dispatcher;
1817
}
18+
#if 0
1919
ScheduledTaskRunner& global_scheduled_task_runner(){
2020
static ScheduledTaskRunner runner(global_async_dispatcher());
2121
return runner;

SerialPrograms/Source/CommonFramework/GlobalServices.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class ScheduledTaskRunner;
1414
class Watchdog;
1515

1616

17-
//AsyncDispatcher& global_async_dispatcher();
17+
AsyncDispatcher& global_async_dispatcher();
1818
//ScheduledTaskRunner& global_scheduled_task_runner();
1919
Watchdog& global_watchdog();
2020

SerialPrograms/Source/CommonFramework/Main.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,10 @@ int main(int argc, char *argv[]){
110110
}
111111

112112
set_working_directory();
113-
send_all_unsent_reports(global_logger_tagged(), true);
114-
113+
114+
// Run this asynchronously to we don't block startup.
115+
std::unique_ptr<AsyncTask> task = send_all_unsent_reports(global_logger_tagged(), true);
116+
115117
int ret = 0;
116118
{
117119
MainWindow w;

SerialPrograms/Source/PokemonLA/Programs/PokemonLA_RegionNavigation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ void mash_A_to_enter_sub_area(
149149
void mash_A_to_change_region(
150150
ProgramEnvironment& env, ConsoleHandle& console, BotBaseContext& context
151151
){
152+
console.log("Waiting for loading screen...");
152153
BlackScreenOverWatcher black_screen0;
153154
int ret = run_until(
154155
console, context,
@@ -165,6 +166,7 @@ void mash_A_to_change_region(
165166
}
166167
context.wait_for(std::chrono::milliseconds(1000));
167168

169+
console.log("Waiting for end of loading screen...");
168170
BlackScreenOverWatcher black_screen1a(COLOR_RED, {0.20, 0.02, 0.60, 0.05}, 150);
169171
BlackScreenOverWatcher black_screen1b(COLOR_RED, {0.20, 0.93, 0.60, 0.05}, 150);
170172
ret = wait_until(

0 commit comments

Comments
 (0)