Retry policy functionality works, resolves #30

This commit is contained in:
Aidan Follestad 2019-01-07 15:50:04 -08:00
commit 69d9eb094e
6 changed files with 87 additions and 31 deletions

View file

@ -50,7 +50,7 @@ class AddSiteActivity : DarkModeSwitchActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_addsite) setContentView(R.layout.activity_addsite)
setupUi(savedInstanceState) setupUi()
lifecycle.addObserver(viewModel) lifecycle.addObserver(viewModel)
@ -114,18 +114,9 @@ class AddSiteActivity : DarkModeSwitchActivity() {
timesData = viewModel.retryPolicyTimes, timesData = viewModel.retryPolicyTimes,
minutesData = viewModel.retryPolicyMinutes minutesData = viewModel.retryPolicyMinutes
) )
// Done button
doneBtn.setOnClickListener {
viewModel.commit {
setResult(RESULT_OK)
finish()
overridePendingTransition(R.anim.fade_out, R.anim.fade_out)
}
}
} }
private fun setupUi(savedInstanceState: Bundle?) { private fun setupUi() {
toolbarTitle.setText(R.string.add_site) toolbarTitle.setText(R.string.add_site)
toolbar.run { toolbar.run {
setNavigationIcon(R.drawable.ic_action_close) setNavigationIcon(R.drawable.ic_action_close)
@ -139,5 +130,14 @@ class AddSiteActivity : DarkModeSwitchActivity() {
) )
validationOptionsAdapter.setDropDownViewResource(R.layout.list_item_spinner_dropdown) validationOptionsAdapter.setDropDownViewResource(R.layout.list_item_spinner_dropdown)
responseValidationMode.adapter = validationOptionsAdapter responseValidationMode.adapter = validationOptionsAdapter
// Done button
doneBtn.setOnClickListener {
viewModel.commit {
setResult(RESULT_OK)
finish()
overridePendingTransition(R.anim.fade_out, R.anim.fade_out)
}
}
} }
} }

View file

@ -149,18 +149,6 @@ class ViewSiteActivity : DarkModeSwitchActivity() {
.toViewText(this, textLastCheckResult) .toViewText(this, textLastCheckResult)
viewModel.onNextCheckText() viewModel.onNextCheckText()
.toViewText(this, textNextCheck) .toViewText(this, textNextCheck)
// Disabled button
viewModel.onDisableChecksVisibility()
.toViewVisibility(this, disableChecksButton)
disableChecksButton.setOnClickListener { maybeDisableChecks() }
// Done button
viewModel.onDoneButtonText()
.toViewText(this, doneBtn)
doneBtn.setOnClickListener {
viewModel.commit { finish() }
}
} }
private fun setupUi() { private fun setupUi() {
@ -195,6 +183,18 @@ class ViewSiteActivity : DarkModeSwitchActivity() {
) )
validationOptionsAdapter.setDropDownViewResource(R.layout.list_item_spinner_dropdown) validationOptionsAdapter.setDropDownViewResource(R.layout.list_item_spinner_dropdown)
responseValidationMode.adapter = validationOptionsAdapter responseValidationMode.adapter = validationOptionsAdapter
// Disabled button
viewModel.onDisableChecksVisibility()
.toViewVisibility(this, disableChecksButton)
disableChecksButton.setOnClickListener { maybeDisableChecks() }
// Done button
viewModel.onDoneButtonText()
.toViewText(this, doneBtn)
doneBtn.setOnClickListener {
viewModel.commit { finish() }
}
} }
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {

View file

@ -39,7 +39,11 @@ data class RetryPolicy(
* In what amount of time (in minutes) we want * In what amount of time (in minutes) we want
* to perform those retries. * to perform those retries.
*/ */
var minutes: Int = 0 var minutes: Int = 0,
/** The timestamp in milliseconds of the last attempt. */
var lastTryTimestamp: Long = 0,
/** How many retries we have left before considering the site to have problem. */
var triesLeft: Int = -1
) : Serializable { ) : Serializable {
constructor() : this(0, 0, 0) constructor() : this(0, 0, 0)
@ -49,6 +53,9 @@ data class RetryPolicy(
// 30 seconds = 30 * 1000 or 30,000 milliseconds. // 30 seconds = 30 * 1000 or 30,000 milliseconds.
// 60,000 / 2 = 30,000. // 60,000 / 2 = 30,000.
fun interval(): Long { fun interval(): Long {
if (count == 0 || minutes == 0) {
return -1
}
val timesPerMinute = count.toFloat() / minutes.toFloat() val timesPerMinute = count.toFloat() / minutes.toFloat()
return MINUTE / timesPerMinute.toInt() return MINUTE / timesPerMinute.toInt()
} }

View file

@ -19,6 +19,7 @@ import android.app.job.JobParameters
import android.app.job.JobService import android.app.job.JobService
import android.content.Intent import android.content.Intent
import com.afollestad.nocknock.data.AppDatabase import com.afollestad.nocknock.data.AppDatabase
import com.afollestad.nocknock.data.RetryPolicy
import com.afollestad.nocknock.data.getSite import com.afollestad.nocknock.data.getSite
import com.afollestad.nocknock.data.model.Site import com.afollestad.nocknock.data.model.Site
import com.afollestad.nocknock.data.model.Status import com.afollestad.nocknock.data.model.Status
@ -139,6 +140,33 @@ class ValidationJob : JobService() {
if (jobResult.lastResult!!.status == OK) { if (jobResult.lastResult!!.status == OK) {
notificationManager.cancelStatusNotification(jobResult) notificationManager.cancelStatusNotification(jobResult)
} else { } else {
val retryPolicy = site.retryPolicy
if (retryPolicy != null) {
log("Check for site ${site.id} was unsuccessful. BUT we have a retryPolicy.")
if (retryPolicy.triesLeft == -1 || retryPolicy.triesLeft > 0) {
if (retryPolicy.triesLeft == -1) {
retryPolicy.triesLeft = retryPolicy.count
} else {
retryPolicy.triesLeft -= 1
}
updateTriesLeft(retryPolicy, retryPolicy.triesLeft)
val interval = retryPolicy.interval()
validationManager.scheduleCheck(
site = jobResult,
fromFinishingJob = true,
overrideDelay = interval
)
log("Scheduling retry in $interval milliseconds.")
return@launch
} else {
updateTriesLeft(retryPolicy, -1)
log("No tries left, continuing to error notification.")
}
}
notificationManager.postStatusNotification(jobResult) notificationManager.postStatusNotification(jobResult)
} }
@ -170,6 +198,13 @@ class ValidationJob : JobService() {
if (status == OK) null if (status == OK) null
else site.lastResult?.reason ?: "Unknown" else site.lastResult?.reason ?: "Unknown"
if (site.retryPolicy != null && status == OK) {
site.retryPolicy = site.retryPolicy!!.copy(
triesLeft = -1,
lastTryTimestamp = 0
)
}
val updatedModel = site.withStatus( val updatedModel = site.withStatus(
status = status, status = status,
timestamp = lastCheckTime, timestamp = lastCheckTime,
@ -184,4 +219,16 @@ class ValidationJob : JobService() {
} }
return updatedModel return updatedModel
} }
private suspend fun updateTriesLeft(
retryPolicy: RetryPolicy,
triesLeft: Int
) {
retryPolicy.triesLeft = triesLeft
withContext(IO) {
database.retryPolicyDao()
.update(retryPolicy)
}
log("Tries left for site ${retryPolicy.siteId}: $triesLeft")
}
} }

View file

@ -51,7 +51,8 @@ interface ValidationManager {
site: Site, site: Site,
rightNow: Boolean = false, rightNow: Boolean = false,
cancelPrevious: Boolean = rightNow, cancelPrevious: Boolean = rightNow,
fromFinishingJob: Boolean = false fromFinishingJob: Boolean = false,
overrideDelay: Long = -1
) )
fun cancelCheck(site: Site) fun cancelCheck(site: Site)
@ -96,7 +97,8 @@ class RealValidationManager(
site: Site, site: Site,
rightNow: Boolean, rightNow: Boolean,
cancelPrevious: Boolean, cancelPrevious: Boolean,
fromFinishingJob: Boolean fromFinishingJob: Boolean,
overrideDelay: Long
) { ) {
check(site.id != 0L) { "Cannot schedule checks for jobs with no ID." } check(site.id != 0L) { "Cannot schedule checks for jobs with no ID." }
val siteSettings = site.settings val siteSettings = site.settings
@ -118,10 +120,10 @@ class RealValidationManager(
val jobInfo = jobInfoProvider.createCheckJob( val jobInfo = jobInfoProvider.createCheckJob(
id = site.id.toInt(), id = site.id.toInt(),
onlyUnmeteredNetwork = false, onlyUnmeteredNetwork = false,
delayMs = if (rightNow) { delayMs = when {
1 rightNow -> 1
} else { overrideDelay > -1 -> overrideDelay
siteSettings.validationIntervalMs else -> siteSettings.validationIntervalMs
}, },
extras = extras, extras = extras,
target = ValidationJob::class.java target = ValidationJob::class.java

View file

@ -10,6 +10,6 @@
<string name="retry_policy">Retry Policy</string> <string name="retry_policy">Retry Policy</string>
<string name="retry_policy_retry">Retry</string> <string name="retry_policy_retry">Retry</string>
<string name="retry_policy_times_in">times in</string> <string name="retry_policy_times_in">times in</string>
<string name="retry_policy_minutes">Minutes</string> <string name="retry_policy_minutes">Minute(s)</string>
</resources> </resources>