Merge lp:~mzanetti/reminders-app/rework-error-handling into lp:reminders-app
- rework-error-handling
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michael Zanetti |
Approved revision: | 14 |
Merged at revision: | 15 |
Proposed branch: | lp:~mzanetti/reminders-app/rework-error-handling |
Merge into: | lp:reminders-app |
Prerequisite: | lp:~mzanetti/reminders-app/use-ssl |
Diff against target: |
877 lines (+292/-250) 17 files modified
src/plugin/Evernote/jobs/createnotejob.cpp (+25/-31) src/plugin/Evernote/jobs/createnotejob.h (+11/-5) src/plugin/Evernote/jobs/deletenotejob.cpp (+8/-9) src/plugin/Evernote/jobs/deletenotejob.h (+5/-3) src/plugin/Evernote/jobs/evernotejob.cpp (+45/-14) src/plugin/Evernote/jobs/evernotejob.h (+21/-2) src/plugin/Evernote/jobs/fetchnotebooksjob.cpp (+8/-12) src/plugin/Evernote/jobs/fetchnotebooksjob.h (+8/-3) src/plugin/Evernote/jobs/fetchnotejob.cpp (+6/-16) src/plugin/Evernote/jobs/fetchnotejob.h (+8/-2) src/plugin/Evernote/jobs/fetchnotesjob.cpp (+6/-13) src/plugin/Evernote/jobs/fetchnotesjob.h (+6/-3) src/plugin/Evernote/jobs/savenotejob.cpp (+26/-32) src/plugin/Evernote/jobs/savenotejob.h (+11/-3) src/plugin/Evernote/note.cpp (+1/-1) src/plugin/Evernote/notesstore.cpp (+71/-93) src/plugin/Evernote/notesstore.h (+26/-8) |
To merge this branch: | bzr merge lp:~mzanetti/reminders-app/rework-error-handling |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Victor Thompson (community) | Approve | ||
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
David Planella | Approve | ||
Review via email: mp+196987@code.launchpad.net |
Commit message
rework error handling and job queue processing.
Description of the change
This reworks how jobs report their results. EvernoteJob.cpp does now all the error handling and tells the job what result code to emit. Creating a new threaded API call now is a matter of copying an existing job and adjusting 2 lines of code.
Along with that I simplified the usage of the job queue. Just create a new job, call enqueue(job) and connect to the jobDone() signal for obtaining results. No need for taking care about processing the queue any more.
Last but not least the simplified error handling made it easy to add a workaround for the connection drops. EvernoteJob.cpp now gives it a second try in case the connection dropped by reopening the connection and starting the job again. In my tests that successfully recovered from 100% of the drops.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Victor Thompson (vthompson) wrote : | # |
1. In notes.h, I believe you'll want to include QQmlParserStatus in a Q_INTERFACES macro.
2. I see you're reworking some of the connection error exception handling. I get the following core dump every so often, I wonder if it's related to an error that isn't being handled.
terminate called after throwing an instance of 'apache:
what(): SSL_write: errno = 110
Aborted (core dumped)
3. Overall the changes to job handling and error handling look good--is there any particular error path that's being fixed that I might be able to try to reproduce? It's a bit hard to try to verify an overall rework of exception handling.
Michael Zanetti (mzanetti) wrote : | # |
> 1. In notes.h, I believe you'll want to include QQmlParserStatus in a
> Q_INTERFACES macro.
Hmm... Why is that?
> 2. I see you're reworking some of the connection error exception handling. I
> get the following core dump every so often, I wonder if it's related to an
> error that isn't being handled.
>
> terminate called after throwing an instance of
> 'apache:
> what(): SSL_write: errno = 110
> Aborted (core dumped)
Interesting. I intentionally only caught the exceptions I could see myself in order to learn about libthrift's behavior. I haven't ever gotten this one. I'll add catching that one and also all the others that can happen in theory as I've seen enough of libthrift by now.
Still, if you could tell me how to reproduce this I could check if there is something else I'm doing wrong and try to prevent it from happening instead of just catching and ignoring.
>
> 3. Overall the changes to job handling and error handling look good--is there
> any particular error path that's being fixed that I might be able to try to
> reproduce? It's a bit hard to try to verify an overall rework of exception
> handling.
Nope, not really. The main reason for this commit is that I didn't want to add the try {} catch() block around every single call to the evernote SDK. So this now offers one place to catch them all and still pass the error code back to the job in a Qt style manner (As Qt intentionally does not use exceptions by design).
David Planella (dpm) wrote : | # |
>> 1. In notes.h, I believe you'll want to include QQmlParserStatus in a
>> Q_INTERFACES macro.
> Hmm... Why is that?
I'm not familiar with this, so take this as a pointer rather than an suggestion, but my guess would be as it's recommended at http://
In any case, I don't see this affecting this MP.
David Planella (dpm) wrote : | # |
I cannot reproduce Victor's core dump after several run tests. Otherwise, LGTM.
In any case, Victor, if you could tell us how to reproduce, we can come back to it.
Michael Zanetti (mzanetti) wrote : | # |
> >> 1. In notes.h, I believe you'll want to include QQmlParserStatus in a
> >> Q_INTERFACES macro.
>
> > Hmm... Why is that?
>
> I'm not familiar with this, so take this as a pointer rather than an
> suggestion, but my guess would be as it's recommended at http://
> project.
>
> In any case, I don't see this affecting this MP.
Oh... now I get it... Yeah. in this merge notes.h still inherits QQmlParserStatus. This has been changed in a newer one. If you want me I can add it in here for completeness, but it would be removed again with the next merge. Sorry for the confusion.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) : | # |
Victor Thompson (vthompson) wrote : | # |
I haven't been able to reproduce. To me it seems like the core happened after letting the app idle while I was reviewing the code. So maybe it was related to the connection timing out.
Michael Zanetti (mzanetti) wrote : | # |
Thanks Victor.
I'll pay extra attention to this.
Preview Diff
1 | === modified file 'src/plugin/Evernote/jobs/createnotejob.cpp' |
2 | --- src/plugin/Evernote/jobs/createnotejob.cpp 2013-11-26 17:18:33 +0000 |
3 | +++ src/plugin/Evernote/jobs/createnotejob.cpp 2013-11-27 21:48:53 +0000 |
4 | @@ -22,36 +22,30 @@ |
5 | |
6 | #include <QDebug> |
7 | |
8 | -CreateNoteJob::CreateNoteJob(Note *note, QObject *parent) : |
9 | +CreateNoteJob::CreateNoteJob(const QString &title, const QString ¬ebookGuid, const QString &content, QObject *parent) : |
10 | EvernoteJob(parent), |
11 | - m_note(note) |
12 | -{ |
13 | -} |
14 | - |
15 | -void CreateNoteJob::run() |
16 | -{ |
17 | - NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError; |
18 | - |
19 | - try { |
20 | - evernote::edam::Note input; |
21 | - input.title = m_note->title().toStdString(); |
22 | - input.__isset.title = true; |
23 | - input.notebookGuid = m_note->notebookGuid().toStdString(); |
24 | - input.__isset.notebookGuid = true; |
25 | - input.content = m_note->content().toStdString(); |
26 | - input.__isset.content = true; |
27 | - input.contentLength = m_note->content().length(); |
28 | - input.__isset.contentLength = true; |
29 | - |
30 | - evernote::edam::Note result; |
31 | - client()->createNote(result, token().toStdString(), input); |
32 | - |
33 | - m_note->setGuid(QString::fromStdString(result.guid)); |
34 | - |
35 | - } catch(evernote::edam::EDAMUserException e) { |
36 | - errorCode = NotesStore::ErrorCodeUserException; |
37 | - } catch(evernote::edam::EDAMSystemException) { |
38 | - errorCode = NotesStore::ErrorCodeSystemException; |
39 | - } |
40 | - emit resultReady(errorCode, m_note); |
41 | + m_title(title), |
42 | + m_notebookGuid(notebookGuid), |
43 | + m_content(content) |
44 | +{ |
45 | +} |
46 | + |
47 | +void CreateNoteJob::startJob() |
48 | +{ |
49 | + evernote::edam::Note input; |
50 | + input.title = m_title.toStdString(); |
51 | + input.__isset.title = true; |
52 | + input.notebookGuid = m_notebookGuid.toStdString(); |
53 | + input.__isset.notebookGuid = true; |
54 | + input.content = m_content.toStdString(); |
55 | + input.__isset.content = true; |
56 | + input.contentLength = m_content.length(); |
57 | + input.__isset.contentLength = true; |
58 | + |
59 | + client()->createNote(m_resultNote, token().toStdString(), input); |
60 | +} |
61 | + |
62 | +void CreateNoteJob::emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage) |
63 | +{ |
64 | + emit jobDone(errorCode, errorMessage, m_resultNote); |
65 | } |
66 | |
67 | === modified file 'src/plugin/Evernote/jobs/createnotejob.h' |
68 | --- src/plugin/Evernote/jobs/createnotejob.h 2013-11-25 00:49:48 +0000 |
69 | +++ src/plugin/Evernote/jobs/createnotejob.h 2013-11-27 21:48:53 +0000 |
70 | @@ -8,15 +8,21 @@ |
71 | { |
72 | Q_OBJECT |
73 | public: |
74 | - explicit CreateNoteJob(Note *note, QObject *parent = 0); |
75 | - |
76 | - void run(); |
77 | + explicit CreateNoteJob(const QString &title, const QString ¬ebookGuid, const QString &content, QObject *parent = 0); |
78 | |
79 | signals: |
80 | - void resultReady(NotesStore::ErrorCode errorCode, Note *note); |
81 | + void jobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage, evernote::edam::Note note); |
82 | + |
83 | +protected: |
84 | + void startJob(); |
85 | + void emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage); |
86 | |
87 | private: |
88 | - Note *m_note; |
89 | + QString m_title; |
90 | + QString m_notebookGuid; |
91 | + QString m_content; |
92 | + |
93 | + evernote::edam::Note m_resultNote; |
94 | }; |
95 | |
96 | #endif // CREATENOTEJOB_H |
97 | |
98 | === modified file 'src/plugin/Evernote/jobs/deletenotejob.cpp' |
99 | --- src/plugin/Evernote/jobs/deletenotejob.cpp 2013-11-26 17:18:33 +0000 |
100 | +++ src/plugin/Evernote/jobs/deletenotejob.cpp 2013-11-27 21:48:53 +0000 |
101 | @@ -26,13 +26,12 @@ |
102 | { |
103 | } |
104 | |
105 | -void DeleteNoteJob::run() |
106 | -{ |
107 | - NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError; |
108 | - try { |
109 | - client()->deleteNote(token().toStdString(), m_guid.toStdString()); |
110 | - } catch(...) { |
111 | - catchTransportException(); |
112 | - } |
113 | - emit resultReady(errorCode, m_guid); |
114 | +void DeleteNoteJob::startJob() |
115 | +{ |
116 | + client()->deleteNote(token().toStdString(), m_guid.toStdString()); |
117 | +} |
118 | + |
119 | +void DeleteNoteJob::emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage) |
120 | +{ |
121 | + emit jobDone(errorCode, errorMessage, m_guid); |
122 | } |
123 | |
124 | === modified file 'src/plugin/Evernote/jobs/deletenotejob.h' |
125 | --- src/plugin/Evernote/jobs/deletenotejob.h 2013-11-25 00:49:48 +0000 |
126 | +++ src/plugin/Evernote/jobs/deletenotejob.h 2013-11-27 21:48:53 +0000 |
127 | @@ -9,10 +9,12 @@ |
128 | public: |
129 | DeleteNoteJob(const QString &guid, QObject *parent = 0); |
130 | |
131 | - void run(); |
132 | - |
133 | signals: |
134 | - void resultReady(NotesStore::ErrorCode errorCode, const QString &guid); |
135 | + void jobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage, const QString &guid); |
136 | + |
137 | +protected: |
138 | + void startJob(); |
139 | + void emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage); |
140 | |
141 | private: |
142 | QString m_guid; |
143 | |
144 | === modified file 'src/plugin/Evernote/jobs/evernotejob.cpp' |
145 | --- src/plugin/Evernote/jobs/evernotejob.cpp 2013-11-26 17:18:33 +0000 |
146 | +++ src/plugin/Evernote/jobs/evernotejob.cpp 2013-11-27 21:48:53 +0000 |
147 | @@ -38,11 +38,55 @@ |
148 | m_token(NotesStore::instance()->token()) |
149 | { |
150 | connect(this, &EvernoteJob::finished, this, &EvernoteJob::deleteLater); |
151 | + connect(this, &EvernoteJob::finished, NotesStore::instance(), &NotesStore::startNextJob); |
152 | } |
153 | |
154 | EvernoteJob::~EvernoteJob() |
155 | { |
156 | - |
157 | +} |
158 | + |
159 | +void EvernoteJob::run() |
160 | +{ |
161 | + if (m_token.isEmpty()) { |
162 | + qWarning() << "No token set. Cannot execute job."; |
163 | + emitJobDone(NotesStore::ErrorCodeUserException, QStringLiteral("No token set.")); |
164 | + return; |
165 | + } |
166 | + |
167 | + try { |
168 | + startJob(); |
169 | + |
170 | + } catch (const TTransportException & e) { |
171 | + |
172 | + // The connection broke down. libthrift + evernote servers seem to be quite flaky |
173 | + // so lets try to start the job once more. |
174 | + qWarning() << "Got a transport exception:" << e.what() << ". Trying to reestablish connection..."; |
175 | + try { |
176 | + NotesStore::instance()->m_httpClient->close(); |
177 | + NotesStore::instance()->m_httpClient->open(); |
178 | + |
179 | + startJob(); |
180 | + } catch (const TTransportException &e) { |
181 | + // Giving up... the connection seems to be down for real. |
182 | + qWarning() << "Cannot reestablish connection:" << e.what(); |
183 | + emitJobDone(NotesStore::ErrorCodeConnectionLost, e.what()); |
184 | + } catch (const evernote::edam::EDAMUserException &e) { |
185 | + emitJobDone(NotesStore::ErrorCodeUserException, e.what()); |
186 | + } catch (const evernote::edam::EDAMSystemException &e) { |
187 | + emitJobDone(NotesStore::ErrorCodeSystemException, e.what()); |
188 | + } catch (const evernote::edam::EDAMNotFoundException &e) { |
189 | + emitJobDone(NotesStore::ErrorCodeNotFoundExcpetion, e.what()); |
190 | + } |
191 | + |
192 | + } catch (const evernote::edam::EDAMUserException &e) { |
193 | + emitJobDone(NotesStore::ErrorCodeUserException, e.what()); |
194 | + } catch (const evernote::edam::EDAMSystemException &e) { |
195 | + emitJobDone(NotesStore::ErrorCodeSystemException, e.what()); |
196 | + } catch (const evernote::edam::EDAMNotFoundException &e) { |
197 | + emitJobDone(NotesStore::ErrorCodeNotFoundExcpetion, e.what()); |
198 | + } |
199 | + |
200 | + emitJobDone(NotesStore::ErrorCodeNoError, QString()); |
201 | } |
202 | |
203 | evernote::edam::NoteStoreClient *EvernoteJob::client() |
204 | @@ -54,16 +98,3 @@ |
205 | { |
206 | return m_token; |
207 | } |
208 | - |
209 | -void EvernoteJob::catchTransportException() |
210 | -{ |
211 | - try { |
212 | - // this function is meant to be called from a catch block |
213 | - // rethrow the exception to catch it again |
214 | - throw; |
215 | - } catch (const TTransportException & e) { |
216 | - qDebug() << e.what(); |
217 | - } catch (const TException & e) { |
218 | - qDebug() << e.what(); |
219 | - } |
220 | -} |
221 | |
222 | === modified file 'src/plugin/Evernote/jobs/evernotejob.h' |
223 | --- src/plugin/Evernote/jobs/evernotejob.h 2013-11-25 00:49:48 +0000 |
224 | +++ src/plugin/Evernote/jobs/evernotejob.h 2013-11-27 21:48:53 +0000 |
225 | @@ -10,6 +10,19 @@ |
226 | |
227 | #include <QThread> |
228 | |
229 | +/* How to create a new Job type: |
230 | + * - Subclass EvernoteJob |
231 | + * - Implement startJob() in which you do the call to evernote. |
232 | + * - No need to catch exceptions, EvernoteJob will deal with those. |
233 | + * - Define a jobDone() signal with the result parameters you need. |
234 | + * - Keep the convention of jobDone(NotesStore::ErrorCode errorCode, const QString &message [, ...]) |
235 | + * - Emit jobDone() in your implementation of emitJobDone(). |
236 | + * - NOTE: emitJobDone() might be called with an error even before startJob() is triggered. |
237 | + * |
238 | + * Jobs can be enqueue()d in NotesStore. |
239 | + * They will destroy themselves when finished. |
240 | + * The jobqueue will take care about starting them. |
241 | + */ |
242 | class EvernoteJob : public QThread |
243 | { |
244 | Q_OBJECT |
245 | @@ -17,12 +30,18 @@ |
246 | explicit EvernoteJob(QObject *parent = 0); |
247 | virtual ~EvernoteJob(); |
248 | |
249 | + void run() final; |
250 | + |
251 | +signals: |
252 | + void connectionLost(const QString &errorMessage); |
253 | + |
254 | protected: |
255 | + virtual void startJob() = 0; |
256 | + virtual void emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage) = 0; |
257 | + |
258 | evernote::edam::NoteStoreClient* client(); |
259 | QString token(); |
260 | |
261 | - void catchTransportException(); |
262 | - |
263 | private: |
264 | QString m_token; |
265 | }; |
266 | |
267 | === modified file 'src/plugin/Evernote/jobs/fetchnotebooksjob.cpp' |
268 | --- src/plugin/Evernote/jobs/fetchnotebooksjob.cpp 2013-11-26 17:18:33 +0000 |
269 | +++ src/plugin/Evernote/jobs/fetchnotebooksjob.cpp 2013-11-27 21:48:53 +0000 |
270 | @@ -28,16 +28,12 @@ |
271 | } |
272 | |
273 | |
274 | -void FetchNotebooksJob::run() |
275 | -{ |
276 | - NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError; |
277 | - std::vector<evernote::edam::Notebook> results; |
278 | - try { |
279 | - client()->listNotebooks(results, token().toStdString()); |
280 | - } catch(evernote::edam::EDAMUserException) { |
281 | - errorCode = NotesStore::ErrorCodeUserException; |
282 | - } catch(evernote::edam::EDAMSystemException) { |
283 | - errorCode = NotesStore::ErrorCodeSystemException; |
284 | - } |
285 | - emit resultReady(errorCode, results); |
286 | +void FetchNotebooksJob::startJob() |
287 | +{ |
288 | + client()->listNotebooks(m_results, token().toStdString()); |
289 | +} |
290 | + |
291 | +void FetchNotebooksJob::emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage) |
292 | +{ |
293 | + emit jobDone(errorCode, errorMessage, m_results); |
294 | } |
295 | |
296 | === modified file 'src/plugin/Evernote/jobs/fetchnotebooksjob.h' |
297 | --- src/plugin/Evernote/jobs/fetchnotebooksjob.h 2013-11-25 00:49:48 +0000 |
298 | +++ src/plugin/Evernote/jobs/fetchnotebooksjob.h 2013-11-27 21:48:53 +0000 |
299 | @@ -9,10 +9,15 @@ |
300 | public: |
301 | explicit FetchNotebooksJob(QObject *parent = 0); |
302 | |
303 | - void run(); |
304 | - |
305 | signals: |
306 | - void resultReady(NotesStore::ErrorCode errorCode, const std::vector<evernote::edam::Notebook> &results); |
307 | + void jobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage, const std::vector<evernote::edam::Notebook> &results); |
308 | + |
309 | +protected: |
310 | + void startJob(); |
311 | + void emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage); |
312 | + |
313 | +private: |
314 | + std::vector<evernote::edam::Notebook> m_results; |
315 | }; |
316 | |
317 | #endif // FETCHNOTEBOOKSJOB_H |
318 | |
319 | === modified file 'src/plugin/Evernote/jobs/fetchnotejob.cpp' |
320 | --- src/plugin/Evernote/jobs/fetchnotejob.cpp 2013-11-26 17:18:33 +0000 |
321 | +++ src/plugin/Evernote/jobs/fetchnotejob.cpp 2013-11-27 21:48:53 +0000 |
322 | @@ -26,22 +26,12 @@ |
323 | { |
324 | } |
325 | |
326 | -void FetchNoteJob::run() |
327 | +void FetchNoteJob::startJob() |
328 | { |
329 | - NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError; |
330 | - evernote::edam::Note result; |
331 | - try { |
332 | - client()->getNote(result, token().toStdString(), m_guid.toStdString(), true, true, false, false); |
333 | - } catch (evernote::edam::EDAMUserException) { |
334 | - errorCode = NotesStore::ErrorCodeUserException; |
335 | - } catch (evernote::edam::EDAMSystemException) { |
336 | - errorCode = NotesStore::ErrorCodeSystemException; |
337 | - } catch (evernote::edam::EDAMNotFoundException) { |
338 | - errorCode = NotesStore::ErrorCodeNotFoundExcpetion; |
339 | - } catch (...) { |
340 | - catchTransportException(); |
341 | - errorCode = NotesStore::ErrorCodeConnectionLost; |
342 | - } |
343 | + client()->getNote(m_result, token().toStdString(), m_guid.toStdString(), true, true, false, false); |
344 | +} |
345 | |
346 | - emit resultReady(errorCode, result); |
347 | +void FetchNoteJob::emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage) |
348 | +{ |
349 | + emit resultReady(errorCode, errorMessage, m_result); |
350 | } |
351 | |
352 | === modified file 'src/plugin/Evernote/jobs/fetchnotejob.h' |
353 | --- src/plugin/Evernote/jobs/fetchnotejob.h 2013-11-25 00:49:48 +0000 |
354 | +++ src/plugin/Evernote/jobs/fetchnotejob.h 2013-11-27 21:48:53 +0000 |
355 | @@ -9,14 +9,20 @@ |
356 | public: |
357 | explicit FetchNoteJob(const QString &guid, QObject *parent = 0); |
358 | |
359 | - void run(); |
360 | signals: |
361 | - void resultReady(NotesStore::ErrorCode error, const evernote::edam::Note ¬e); |
362 | + void resultReady(NotesStore::ErrorCode error, const QString &errorMessage, const evernote::edam::Note ¬e); |
363 | + |
364 | +protected: |
365 | + void startJob(); |
366 | + void emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage); |
367 | |
368 | private: |
369 | evernote::edam::NoteStoreClient *m_client; |
370 | QString m_token; |
371 | QString m_guid; |
372 | + |
373 | + evernote::edam::Note m_result; |
374 | + |
375 | }; |
376 | |
377 | #endif // FETCHNOTEJOB_H |
378 | |
379 | === modified file 'src/plugin/Evernote/jobs/fetchnotesjob.cpp' |
380 | --- src/plugin/Evernote/jobs/fetchnotesjob.cpp 2013-11-26 17:18:33 +0000 |
381 | +++ src/plugin/Evernote/jobs/fetchnotesjob.cpp 2013-11-27 21:48:53 +0000 |
382 | @@ -30,7 +30,7 @@ |
383 | { |
384 | } |
385 | |
386 | -void FetchNotesJob::run() |
387 | +void FetchNotesJob::startJob() |
388 | { |
389 | // TODO: fix start/end (use smaller chunks and continue fetching if there are more notes available) |
390 | int32_t start = 0; |
391 | @@ -48,17 +48,10 @@ |
392 | resultSpec.includeTitle = true; |
393 | resultSpec.__isset.includeTitle = true; |
394 | |
395 | - NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError; |
396 | - evernote::edam::NotesMetadataList results; |
397 | + client()->findNotesMetadata(m_results, token().toStdString(), filter, start, end, resultSpec); |
398 | +} |
399 | |
400 | - try { |
401 | - client()->findNotesMetadata(results, token().toStdString(), filter, start, end, resultSpec); |
402 | - } catch(evernote::edam::EDAMUserException) { |
403 | - errorCode = NotesStore::ErrorCodeUserException; |
404 | - } catch(evernote::edam::EDAMSystemException) { |
405 | - errorCode = NotesStore::ErrorCodeSystemException; |
406 | - } catch(evernote::edam::EDAMNotFoundException) { |
407 | - errorCode = NotesStore::ErrorCodeNotFoundExcpetion; |
408 | - } |
409 | - emit resultReady(errorCode, results); |
410 | +void FetchNotesJob::emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage) |
411 | +{ |
412 | + emit jobDone(errorCode, errorMessage, m_results); |
413 | } |
414 | |
415 | === modified file 'src/plugin/Evernote/jobs/fetchnotesjob.h' |
416 | --- src/plugin/Evernote/jobs/fetchnotesjob.h 2013-11-25 00:49:48 +0000 |
417 | +++ src/plugin/Evernote/jobs/fetchnotesjob.h 2013-11-27 21:48:53 +0000 |
418 | @@ -9,13 +9,16 @@ |
419 | public: |
420 | explicit FetchNotesJob(const QString &filterNotebookGuid, QObject *parent = 0); |
421 | |
422 | - void run(); |
423 | - |
424 | signals: |
425 | - void resultReady(NotesStore::ErrorCode errorCode, const evernote::edam::NotesMetadataList &results); |
426 | + void jobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::NotesMetadataList &results); |
427 | + |
428 | +protected: |
429 | + void startJob(); |
430 | + void emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage); |
431 | |
432 | private: |
433 | QString m_filterNotebookGuid; |
434 | + evernote::edam::NotesMetadataList m_results; |
435 | }; |
436 | |
437 | #endif // FETCHNOTESJOB_H |
438 | |
439 | === modified file 'src/plugin/Evernote/jobs/savenotejob.cpp' |
440 | --- src/plugin/Evernote/jobs/savenotejob.cpp 2013-11-26 17:18:33 +0000 |
441 | +++ src/plugin/Evernote/jobs/savenotejob.cpp 2013-11-27 21:48:53 +0000 |
442 | @@ -25,36 +25,30 @@ |
443 | |
444 | SaveNoteJob::SaveNoteJob(Note *note, QObject *parent) : |
445 | EvernoteJob(parent), |
446 | - m_note(note) |
447 | -{ |
448 | -} |
449 | - |
450 | -void SaveNoteJob::run() |
451 | -{ |
452 | - NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError; |
453 | - try { |
454 | - evernote::edam::Note note; |
455 | - note.guid = m_note->guid().toStdString(); |
456 | - note.__isset.guid = true; |
457 | - note.title = m_note->title().toStdString(); |
458 | - note.__isset.title = true; |
459 | - note.notebookGuid = m_note->notebookGuid().toStdString(); |
460 | - note.__isset.notebookGuid = true; |
461 | - note.content = m_note->content().toStdString(); |
462 | - note.__isset.content = true; |
463 | - note.contentLength = m_note->content().length(); |
464 | - |
465 | - client()->updateNote(note, token().toStdString(), note); |
466 | - |
467 | - } catch (evernote::edam::EDAMUserException e) { |
468 | - errorCode = NotesStore::ErrorCodeUserException; |
469 | - qDebug() << QString::fromStdString(e.parameter); |
470 | - } catch (evernote::edam::EDAMSystemException) { |
471 | - errorCode = NotesStore::ErrorCodeSystemException; |
472 | - } catch (...) { |
473 | - catchTransportException(); |
474 | - errorCode = NotesStore::ErrorCodeConnectionLost; |
475 | - } |
476 | - |
477 | - emit resultReady(errorCode, m_note); |
478 | + m_guid(note->guid()), |
479 | + m_title(note->title()), |
480 | + m_notebookGuid(note->notebookGuid()), |
481 | + m_content(note->content()) |
482 | +{ |
483 | +} |
484 | + |
485 | +void SaveNoteJob::startJob() |
486 | +{ |
487 | + evernote::edam::Note note; |
488 | + note.guid = m_guid.toStdString(); |
489 | + note.__isset.guid = true; |
490 | + note.title = m_title.toStdString(); |
491 | + note.__isset.title = true; |
492 | + note.notebookGuid = m_notebookGuid.toStdString(); |
493 | + note.__isset.notebookGuid = true; |
494 | + note.content = m_content.toStdString(); |
495 | + note.__isset.content = true; |
496 | + note.contentLength = m_content.length(); |
497 | + |
498 | + client()->updateNote(m_note, token().toStdString(), note); |
499 | +} |
500 | + |
501 | +void SaveNoteJob::emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage) |
502 | +{ |
503 | + emit jobDone(errorCode, errorMessage, m_note); |
504 | } |
505 | |
506 | === modified file 'src/plugin/Evernote/jobs/savenotejob.h' |
507 | --- src/plugin/Evernote/jobs/savenotejob.h 2013-11-25 00:49:48 +0000 |
508 | +++ src/plugin/Evernote/jobs/savenotejob.h 2013-11-27 21:48:53 +0000 |
509 | @@ -9,12 +9,20 @@ |
510 | public: |
511 | explicit SaveNoteJob(Note *note, QObject *parent = 0); |
512 | |
513 | - void run(); |
514 | signals: |
515 | - void resultReady(NotesStore::ErrorCode errorCode, Note *note); |
516 | + void jobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note ¬e); |
517 | + |
518 | +protected: |
519 | + void startJob(); |
520 | + void emitJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage); |
521 | |
522 | private: |
523 | - Note *m_note; |
524 | + QString m_guid; |
525 | + QString m_title; |
526 | + QString m_notebookGuid; |
527 | + QString m_content; |
528 | + |
529 | + evernote::edam::Note m_note; |
530 | }; |
531 | |
532 | #endif // SAVENOTEJOB_H |
533 | |
534 | === modified file 'src/plugin/Evernote/note.cpp' |
535 | --- src/plugin/Evernote/note.cpp 2013-11-26 17:18:33 +0000 |
536 | +++ src/plugin/Evernote/note.cpp 2013-11-27 21:48:53 +0000 |
537 | @@ -35,7 +35,7 @@ |
538 | |
539 | void Note::setGuid(const QString &guid) |
540 | { |
541 | - if (m_guid == guid) { |
542 | + if (m_guid != guid) { |
543 | m_guid = guid; |
544 | emit guidChanged(); |
545 | } |
546 | |
547 | === modified file 'src/plugin/Evernote/notesstore.cpp' |
548 | --- src/plugin/Evernote/notesstore.cpp 2013-11-27 21:48:53 +0000 |
549 | +++ src/plugin/Evernote/notesstore.cpp 2013-11-27 21:48:53 +0000 |
550 | @@ -77,12 +77,12 @@ |
551 | } |
552 | |
553 | boost::shared_ptr<TBufferedTransport> bufferedTransport(new TBufferedTransport(socket)); |
554 | - boost::shared_ptr<THttpClient> userStoreHttpClient (new THttpClient(bufferedTransport, |
555 | + m_httpClient = boost::shared_ptr<THttpClient>(new THttpClient(bufferedTransport, |
556 | EVERNOTE_HOST.toStdString(), |
557 | EDAM_USER_STORE_PATH.toStdString())); |
558 | - userStoreHttpClient->open(); |
559 | + m_httpClient->open(); |
560 | |
561 | - boost::shared_ptr<TProtocol> iprot(new TBinaryProtocol(userStoreHttpClient)); |
562 | + boost::shared_ptr<TProtocol> iprot(new TBinaryProtocol(m_httpClient)); |
563 | m_client = new evernote::edam::NoteStoreClient(iprot); |
564 | |
565 | qDebug() << "NoteStore client created."; |
566 | @@ -153,27 +153,6 @@ |
567 | return m_notes.value(guid); |
568 | } |
569 | |
570 | -void NotesStore::saveNote(const QString &guid) |
571 | -{ |
572 | - Note *note = m_notes.value(guid); |
573 | - |
574 | - QString enml = Html2EnmlConverter::html2enml(note->content()); |
575 | - note->setContent(enml); |
576 | - |
577 | - SaveNoteJob *job = new SaveNoteJob(note, this); |
578 | - connect(job, &SaveNoteJob::resultReady, this, &NotesStore::saveNoteJobDone); |
579 | - m_jobQueue.append(job); |
580 | - startJobQueue(); |
581 | -} |
582 | - |
583 | -void NotesStore::deleteNote(const QString &guid) |
584 | -{ |
585 | - DeleteNoteJob *job = new DeleteNoteJob(guid, this); |
586 | - connect(job, &DeleteNoteJob::resultReady, this, &NotesStore::deleteNoteJobDone); |
587 | - m_jobQueue.append(job); |
588 | - startJobQueue(); |
589 | -} |
590 | - |
591 | QList<Notebook *> NotesStore::notebooks() const |
592 | { |
593 | return m_notebooks.values(); |
594 | @@ -184,6 +163,12 @@ |
595 | return m_notebooks.value(guid); |
596 | } |
597 | |
598 | +void NotesStore::enqueue(EvernoteJob *job) |
599 | +{ |
600 | + m_jobQueue.append(job); |
601 | + startJobQueue(); |
602 | +} |
603 | + |
604 | void NotesStore::startJobQueue() |
605 | { |
606 | if (m_jobQueue.isEmpty()) { |
607 | @@ -205,23 +190,15 @@ |
608 | |
609 | void NotesStore::refreshNotes(const QString &filterNotebookGuid) |
610 | { |
611 | - if (m_token.isEmpty()) { |
612 | - qWarning() << "No token set. Cannot fetch notes."; |
613 | - return; |
614 | - } |
615 | - |
616 | FetchNotesJob *job = new FetchNotesJob(filterNotebookGuid); |
617 | - connect(job, &FetchNotesJob::resultReady, this, &NotesStore::fetchNotesJobDone); |
618 | - |
619 | - m_jobQueue.append(job); |
620 | - startJobQueue(); |
621 | + connect(job, &FetchNotesJob::jobDone, this, &NotesStore::fetchNotesJobDone); |
622 | + enqueue(job); |
623 | } |
624 | |
625 | -void NotesStore::fetchNotesJobDone(ErrorCode errorCode, const evernote::edam::NotesMetadataList &results) |
626 | +void NotesStore::fetchNotesJobDone(ErrorCode errorCode, const QString &errorMessage, const evernote::edam::NotesMetadataList &results) |
627 | { |
628 | if (errorCode != ErrorCodeNoError) { |
629 | - qWarning() << "Failed to fetch notes list:" << errorCodeToString(errorCode); |
630 | - startNextJob(); |
631 | + qWarning() << "Failed to fetch notes list:" << errorMessage; |
632 | return; |
633 | } |
634 | |
635 | @@ -240,29 +217,19 @@ |
636 | emit noteAdded(note->guid()); |
637 | } |
638 | } |
639 | - |
640 | - startNextJob(); |
641 | } |
642 | |
643 | void NotesStore::refreshNoteContent(const QString &guid) |
644 | { |
645 | - if (m_token.isEmpty()) { |
646 | - qWarning() << "No token set. Cannot fetch note."; |
647 | - return; |
648 | - } |
649 | - |
650 | FetchNoteJob *job = new FetchNoteJob(guid, this); |
651 | connect(job, &FetchNoteJob::resultReady, this, &NotesStore::fetchNoteJobDone); |
652 | - m_jobQueue.append(job); |
653 | - |
654 | - startJobQueue(); |
655 | + enqueue(job); |
656 | } |
657 | |
658 | -void NotesStore::fetchNoteJobDone(ErrorCode errorCode, const evernote::edam::Note &result) |
659 | +void NotesStore::fetchNoteJobDone(ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result) |
660 | { |
661 | if (errorCode != ErrorCodeNoError) { |
662 | - qWarning() << "Error fetching note:" << errorCode; |
663 | - startNextJob(); |
664 | + qWarning() << "Error fetching note:" << errorMessage; |
665 | return; |
666 | } |
667 | |
668 | @@ -271,29 +238,19 @@ |
669 | note->setTitle(QString::fromStdString(result.title)); |
670 | note->setContent(QString::fromStdString(result.content)); |
671 | emit noteChanged(note->guid()); |
672 | - |
673 | - startNextJob(); |
674 | } |
675 | |
676 | void NotesStore::refreshNotebooks() |
677 | { |
678 | - if (m_token.isEmpty()) { |
679 | - qWarning() << "No token set. Cannot refresh notebooks."; |
680 | - return; |
681 | - } |
682 | - |
683 | FetchNotebooksJob *job = new FetchNotebooksJob(); |
684 | - connect(job, &FetchNotebooksJob::resultReady, this, &NotesStore::fetchNotebooksJobDone); |
685 | - |
686 | - m_jobQueue.append(job); |
687 | - startJobQueue(); |
688 | + connect(job, &FetchNotebooksJob::jobDone, this, &NotesStore::fetchNotebooksJobDone); |
689 | + enqueue(job); |
690 | } |
691 | |
692 | -void NotesStore::fetchNotebooksJobDone(ErrorCode errorCode, const std::vector<evernote::edam::Notebook> &results) |
693 | +void NotesStore::fetchNotebooksJobDone(ErrorCode errorCode, const QString &errorMessage, const std::vector<evernote::edam::Notebook> &results) |
694 | { |
695 | if (errorCode != ErrorCodeNoError) { |
696 | - qWarning() << "Error fetching notebooks:" << errorCodeToString(errorCode); |
697 | - startNextJob(); |
698 | + qWarning() << "Error fetching notebooks:" << errorMessage; |
699 | return; |
700 | } |
701 | |
702 | @@ -312,51 +269,72 @@ |
703 | qDebug() << "got new notebook" << notebook->guid(); |
704 | } |
705 | } |
706 | - |
707 | - startNextJob(); |
708 | } |
709 | |
710 | void NotesStore::createNote(const QString &title, const QString ¬ebookGuid, const QString &content) |
711 | { |
712 | - Note *note = new Note(); |
713 | - note->setTitle(title); |
714 | - note->setNotebookGuid(notebookGuid); |
715 | - note->setContent(content); |
716 | - CreateNoteJob *job = new CreateNoteJob(note); |
717 | - connect(job, &CreateNoteJob::resultReady, this, &NotesStore::createNoteJobDone); |
718 | - |
719 | - m_jobQueue.append(job); |
720 | - startJobQueue(); |
721 | + CreateNoteJob *job = new CreateNoteJob(title, notebookGuid, content); |
722 | + connect(job, &CreateNoteJob::jobDone, this, &NotesStore::createNoteJobDone); |
723 | + enqueue(job); |
724 | } |
725 | |
726 | -void NotesStore::createNoteJobDone(NotesStore::ErrorCode errorCode, Note *note) |
727 | +void NotesStore::createNoteJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result) |
728 | { |
729 | if (errorCode != ErrorCodeNoError) { |
730 | - qWarning() << "Error creating note:" << errorCodeToString(errorCode); |
731 | - delete note; |
732 | - startNextJob(); |
733 | + qWarning() << "Error creating note:" << errorMessage; |
734 | return; |
735 | } |
736 | |
737 | + Note *note = new Note(QString::fromStdString(result.guid)); |
738 | + note->setNotebookGuid(QString::fromStdString(result.notebookGuid)); |
739 | + note->setTitle(QString::fromStdString(result.title)); |
740 | + note->setContent(QString::fromStdString(result.content)); |
741 | + |
742 | m_notes.insert(note->guid(), note); |
743 | noteAdded(note->guid()); |
744 | - startNextJob(); |
745 | -} |
746 | - |
747 | -void NotesStore::saveNoteJobDone(NotesStore::ErrorCode errorCode, Note *note) |
748 | -{ |
749 | - startNextJob(); |
750 | -} |
751 | - |
752 | -void NotesStore::deleteNoteJobDone(NotesStore::ErrorCode errorCode, const QString &guid) |
753 | -{ |
754 | - if (errorCode != ErrorCodeNoError) { |
755 | - qWarning() << "Cannot delete note:" << errorCodeToString(errorCode); |
756 | - startNextJob(); |
757 | +} |
758 | + |
759 | +void NotesStore::saveNote(const QString &guid) |
760 | +{ |
761 | + Note *note = m_notes.value(guid); |
762 | + |
763 | + QString enml = Html2EnmlConverter::html2enml(note->content()); |
764 | + note->setContent(enml); |
765 | + |
766 | + SaveNoteJob *job = new SaveNoteJob(note, this); |
767 | + connect(job, &SaveNoteJob::jobDone, this, &NotesStore::saveNoteJobDone); |
768 | + enqueue(job); |
769 | +} |
770 | + |
771 | +void NotesStore::saveNoteJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result) |
772 | +{ |
773 | + if (errorCode != ErrorCodeNoError) { |
774 | + qWarning() << "error saving note" << errorMessage; |
775 | + return; |
776 | + } |
777 | + |
778 | + Note *note = m_notes.value(QString::fromStdString(result.guid)); |
779 | + if (note) { |
780 | + note->setTitle(QString::fromStdString(result.title)); |
781 | + note->setNotebookGuid(QString::fromStdString(result.notebookGuid)); |
782 | + |
783 | + emit noteChanged(note->guid()); |
784 | + } |
785 | +} |
786 | + |
787 | +void NotesStore::deleteNote(const QString &guid) |
788 | +{ |
789 | + DeleteNoteJob *job = new DeleteNoteJob(guid, this); |
790 | + connect(job, &DeleteNoteJob::jobDone, this, &NotesStore::deleteNoteJobDone); |
791 | + enqueue(job); |
792 | +} |
793 | + |
794 | +void NotesStore::deleteNoteJobDone(NotesStore::ErrorCode errorCode, const QString &errorMessage, const QString &guid) |
795 | +{ |
796 | + if (errorCode != ErrorCodeNoError) { |
797 | + qWarning() << "Cannot delete note:" << errorMessage; |
798 | return; |
799 | } |
800 | emit noteRemoved(guid); |
801 | m_notes.take(guid)->deleteLater(); |
802 | - startNextJob(); |
803 | } |
804 | - |
805 | |
806 | === modified file 'src/plugin/Evernote/notesstore.h' |
807 | --- src/plugin/Evernote/notesstore.h 2013-11-25 00:49:48 +0000 |
808 | +++ src/plugin/Evernote/notesstore.h 2013-11-27 21:48:53 +0000 |
809 | @@ -1,6 +1,9 @@ |
810 | #ifndef NOTESSTORE_H |
811 | #define NOTESSTORE_H |
812 | |
813 | +// Thrift |
814 | +#include <transport/THttpClient.h> |
815 | + |
816 | // Evernote SDK |
817 | #include <NoteStore.h> |
818 | #include <NoteStore_constants.h> |
819 | @@ -14,6 +17,8 @@ |
820 | class Notebook; |
821 | class Note; |
822 | |
823 | +using namespace apache::thrift::transport; |
824 | + |
825 | class NotesStore : public QObject |
826 | { |
827 | Q_OBJECT |
828 | @@ -63,14 +68,19 @@ |
829 | void notebookChanged(const QString &guid); |
830 | |
831 | private slots: |
832 | - void fetchNotesJobDone(ErrorCode errorCode, const evernote::edam::NotesMetadataList &results); |
833 | - void fetchNotebooksJobDone(ErrorCode errorCode, const std::vector<evernote::edam::Notebook> &results); |
834 | - void fetchNoteJobDone(ErrorCode errorCode, const evernote::edam::Note &result); |
835 | - void createNoteJobDone(ErrorCode errorCode, Note *note); |
836 | - void saveNoteJobDone(ErrorCode errorCode, Note *note); |
837 | - void deleteNoteJobDone(ErrorCode errorCode, const QString &guid); |
838 | + void fetchNotesJobDone(ErrorCode errorCode, const QString &errorMessage, const evernote::edam::NotesMetadataList &results); |
839 | + void fetchNotebooksJobDone(ErrorCode errorCode, const QString &errorMessage, const std::vector<evernote::edam::Notebook> &results); |
840 | + void fetchNoteJobDone(ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result); |
841 | + void createNoteJobDone(ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result); |
842 | + void saveNoteJobDone(ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result); |
843 | + void deleteNoteJobDone(ErrorCode errorCode, const QString &errorMessage, const QString &guid); |
844 | |
845 | + // Use this to enqueue a new job. It will automatically start it if there is no other job pending. |
846 | + void enqueue(EvernoteJob *job); |
847 | void startJobQueue(); |
848 | + |
849 | + // You should not use this. It's called by the job queue. |
850 | + // If you have a new job to run, just enqueue it. The queue will process it eventually. |
851 | void startNextJob(); |
852 | |
853 | private: |
854 | @@ -78,13 +88,21 @@ |
855 | static NotesStore *s_instance; |
856 | |
857 | QString m_token; |
858 | - evernote::edam::NoteStoreClient *m_client; |
859 | |
860 | QHash<QString, Notebook*> m_notebooks; |
861 | QHash<QString, Note*> m_notes; |
862 | |
863 | + // There must be only one job running at a time |
864 | + // Do not start jobs other than with startJobQueue() |
865 | QList<EvernoteJob*> m_jobQueue; |
866 | - QThread *m_currentJob; |
867 | + EvernoteJob *m_currentJob; |
868 | + |
869 | + // Those two are accessed from the job thread. |
870 | + // Make sure to not access them while any jobs are running |
871 | + // or we need to mutex them. |
872 | + evernote::edam::NoteStoreClient *m_client; |
873 | + boost::shared_ptr<THttpClient> m_httpClient; |
874 | + |
875 | }; |
876 | |
877 | #endif // NOTESSTORE_H |
PASSED: Continuous integration, rev:14 91.189. 93.70:8080/ job/reminders- app-ci/ 29/ 91.189. 93.70:8080/ job/generic- mediumtests- trusty/ 309 91.189. 93.70:8080/ job/reminders- app-saucy- amd64-ci/ 29 91.189. 93.70:8080/ job/reminders- app-trusty- amd64-ci/ 29
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/reminders- app-ci/ 29/rebuild
http://