-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Queue show notes downloading #1390
Conversation
fun toDate(value: Long?): Date? { | ||
return if (value == null) null else Date(value) | ||
fun toDate(value: Long?): Date { | ||
return if (value == null) Date() else Date(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should stop the following Sentry error.
au.com.shiftyjelly.pocketcasts.models.db.dao.EpisodeDao_Impl$44 in call
IllegalStateException
Expected non-null java.util.Date, but it was null.
It seems like the database episode has a publish date of null. I can't find how this is possible but this should stop the crash happening when the data is read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job avoiding this crash. I wonder if returning a dynamic date might not be the best approach though.
I'm not sure about this, but maybe we'd be better off returning a static date object (i.e., something like the UNIX epoch), so the behavior is consistent and doesn't return something different each time it is called with null
. 🤔 This is just me thinking out loud. I'm seriously not sure here.
I think it would be good to log a Sentry breadcrumb here if the Long
is null, so that if this somehow causes a problem later on that shows up in Sentry, this will get flagged for us. Something like:
if (value == null) {
Sentry.addBreadcrumb("DateTypeConverter.toDate() Long parameter is null. Returning default date")
Date.from(Instant.EPOCH)
} else Date(value)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe LogBuffer.log
would be better than just adding the breadcrumb.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent idea to log and return a constant date. I have made this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That log just saved me! It gets called with dates that need to be null. I'm reverting this issue fix.
Timber.i(e, message) | ||
} else { | ||
Timber.e(e, message) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should stop the following Sentry error as I can see the previous call is the ratings endpoint.
HttpException
HTTP 404
@@ -125,13 +126,13 @@ class DownloadEpisodeTask @AssistedInject constructor( | |||
this.episode = runBlocking { episodeManager.findEpisodeByUuid(episodeUUID!!) } ?: return Result.failure() | |||
|
|||
if (this.episode.downloadTaskId != id.toString()) { | |||
LogBuffer.e(LogBuffer.TAG_BACKGROUND_TASKS, "Mismatched download task id for episode ${episode.title}. Cancelling.") | |||
LogBuffer.i(LogBuffer.TAG_BACKGROUND_TASKS, "Mismatched download task id for episode ${episode.title}. Cancelling.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few issues reported in this class that are being sent to Sentry. If we aren't going address them I believe they should just be the log level of info
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with the other places you've made this change, but I wonder if we should keep this one since if it shot up all of a sudden that might be an issue we'd want to know about.
This isn't something you changed, but while we're here, do you think it would be worth including the downloadTaskId
and id
in the error message. Seems like that would be helpful in tracking down why these are occurring. Just a thought, I don't feel strongly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have kept this and added the extra ids in the message. Thanks for the suggestions.
c15ca38
to
0a578a8
Compare
SentryHelper.recordException(e) | ||
} | ||
info("Worker failed - took ${SystemClock.elapsedRealtime() - startTime} ms") | ||
val logPriority = if (e is HttpException) Log.INFO else Log.ERROR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if there is a better way to do this. Maybe I should add a common way to add network exceptions which doesn't report to Sentry. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not a bad idea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice work. Just had a couple of comments/questions, but nothing big. This is a great improvement. 🤩
fun toDate(value: Long?): Date? { | ||
return if (value == null) null else Date(value) | ||
fun toDate(value: Long?): Date { | ||
return if (value == null) Date() else Date(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job avoiding this crash. I wonder if returning a dynamic date might not be the best approach though.
I'm not sure about this, but maybe we'd be better off returning a static date object (i.e., something like the UNIX epoch), so the behavior is consistent and doesn't return something different each time it is called with null
. 🤔 This is just me thinking out loud. I'm seriously not sure here.
I think it would be good to log a Sentry breadcrumb here if the Long
is null, so that if this somehow causes a problem later on that shows up in Sentry, this will get flagged for us. Something like:
if (value == null) {
Sentry.addBreadcrumb("DateTypeConverter.toDate() Long parameter is null. Returning default date")
Date.from(Instant.EPOCH)
} else Date(value)
.addTag(episode.uuid) | ||
.setConstraints(constraints) | ||
.build() | ||
WorkManager.getInstance(context).beginUniqueWork(TASK_NAME, ExistingWorkPolicy.APPEND, workRequest).enqueue() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is APPEND
here better than APPEND_OR_REPLACE
? I'm not particularly familiar with this, so I may be misunderstanding, but I was thinking that APPEND_OR_REPLACE
might be better to avoid dropping subsequent tasks if an early one fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The show notes task always returns Result.success()
so I think this shouldn't matter but it seems like a safer option, I will change it.
SentryHelper.recordException(e) | ||
} | ||
info("Worker failed - took ${SystemClock.elapsedRealtime() - startTime} ms") | ||
val logPriority = if (e is HttpException) Log.INFO else Log.ERROR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not a bad idea
fun toDate(value: Long?): Date? { | ||
return if (value == null) null else Date(value) | ||
fun toDate(value: Long?): Date { | ||
return if (value == null) Date() else Date(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe LogBuffer.log
would be better than just adding the breadcrumb.
@@ -125,13 +126,13 @@ class DownloadEpisodeTask @AssistedInject constructor( | |||
this.episode = runBlocking { episodeManager.findEpisodeByUuid(episodeUUID!!) } ?: return Result.failure() | |||
|
|||
if (this.episode.downloadTaskId != id.toString()) { | |||
LogBuffer.e(LogBuffer.TAG_BACKGROUND_TASKS, "Mismatched download task id for episode ${episode.title}. Cancelling.") | |||
LogBuffer.i(LogBuffer.TAG_BACKGROUND_TASKS, "Mismatched download task id for episode ${episode.title}. Cancelling.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with the other places you've made this change, but I wonder if we should keep this one since if it shot up all of a sudden that might be an issue we'd want to know about.
This isn't something you changed, but while we're here, do you think it would be worth including the downloadTaskId
and id
in the error message. Seems like that would be helpful in tracking down why these are occurring. Just a thought, I don't feel strongly.
return try { | ||
showNotesManager.downloadShowNotes(podcastUuid = podcastUuid, episodeUuid = episodeUuid) | ||
showNotesManager.downloadToCacheShowNotes(podcastUuid = podcastUuid) | ||
info("Worker completed - took ${SystemClock.elapsedRealtime() - startTime} ms") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Including the timing here is nice!
fun log(priority: Int, tag: String, throwable: Throwable, message: String, vararg args: Any) { | ||
addLog(priority, tag, throwable, message, *args) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of adding a new log
method, could we get the same effect by renaming addLog
to log
and making that public? Certainly not a big deal, but it feels a bit more straightforward.
725f6f5
to
5efd4f8
Compare
Description
After doing some debugging with the Background Task Inspector, I noticed that when you download multiple episodes at once, the show notes tasks run in parallel. A single queue that caches the show notes seems to be a better approach. If you download multiple episodes from the same podcast the show notes will be cached with the first call, before the same file would be downloaded multiple times until the cache was populated.
This PR also stops some reports to Sentry, I will comment on them inline.
Testing Instructions