mirror of
https://github.com/afollestad/nock-nock.git
synced 2025-04-20 19:45:17 +00:00
Configurable response timeouts, resolves #31
This commit is contained in:
parent
7e46b84d08
commit
62ef385b65
15 changed files with 220 additions and 40 deletions
|
@ -22,12 +22,14 @@ import com.afollestad.nocknock.viewcomponents.ext.conceal
|
|||
import com.afollestad.nocknock.viewcomponents.ext.onItemSelected
|
||||
import com.afollestad.nocknock.viewcomponents.ext.onLayout
|
||||
import com.afollestad.nocknock.viewcomponents.ext.showOrHide
|
||||
import com.afollestad.nocknock.viewcomponents.ext.textAsInt
|
||||
import com.afollestad.nocknock.viewcomponents.ext.trimmedText
|
||||
import kotlinx.android.synthetic.main.activity_addsite.checkIntervalLayout
|
||||
import kotlinx.android.synthetic.main.activity_addsite.doneBtn
|
||||
import kotlinx.android.synthetic.main.activity_addsite.inputName
|
||||
import kotlinx.android.synthetic.main.activity_addsite.inputUrl
|
||||
import kotlinx.android.synthetic.main.activity_addsite.loadingProgress
|
||||
import kotlinx.android.synthetic.main.activity_addsite.responseTimeoutInput
|
||||
import kotlinx.android.synthetic.main.activity_addsite.responseValidationMode
|
||||
import kotlinx.android.synthetic.main.activity_addsite.responseValidationSearchTerm
|
||||
import kotlinx.android.synthetic.main.activity_addsite.rootView
|
||||
|
@ -99,6 +101,7 @@ class AddSiteActivity : AppCompatActivity(), AddSiteView {
|
|||
val checkInterval = checkIntervalLayout.getSelectedCheckInterval()
|
||||
val validationMode =
|
||||
responseValidationMode.selectedItemPosition.indexToValidationMode()
|
||||
val defaultTimeout = getString(R.string.response_timeout_default).toInt()
|
||||
|
||||
isClosing = true
|
||||
presenter.commit(
|
||||
|
@ -106,7 +109,8 @@ class AddSiteActivity : AppCompatActivity(), AddSiteView {
|
|||
url = inputUrl.trimmedText(),
|
||||
checkInterval = checkInterval,
|
||||
validationMode = validationMode,
|
||||
validationContent = validationMode.validationContent()
|
||||
validationContent = validationMode.validationContent(),
|
||||
networkTimeout = responseTimeoutInput.textAsInt(defaultValue = defaultTimeout)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -165,6 +169,11 @@ class AddSiteActivity : AppCompatActivity(), AddSiteView {
|
|||
null
|
||||
}
|
||||
)
|
||||
responseTimeoutInput.error = if (errors.networkTimeout != null) {
|
||||
getString(errors.networkTimeout!!)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSiteAdded() {
|
||||
|
|
|
@ -27,11 +27,12 @@ data class InputErrors(
|
|||
var url: Int? = null,
|
||||
var checkInterval: Int? = null,
|
||||
var termSearch: Int? = null,
|
||||
var javaScript: Int? = null
|
||||
var javaScript: Int? = null,
|
||||
var networkTimeout: Int? = null
|
||||
) {
|
||||
@CheckResult fun any(): Boolean {
|
||||
return name != null || url != null || checkInterval != null ||
|
||||
termSearch != null || javaScript != null
|
||||
termSearch != null || javaScript != null || networkTimeout != null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +53,8 @@ interface AddSitePresenter {
|
|||
url: String,
|
||||
checkInterval: Long,
|
||||
validationMode: ValidationMode,
|
||||
validationContent: String?
|
||||
validationContent: String?,
|
||||
networkTimeout: Int
|
||||
)
|
||||
|
||||
fun dropView()
|
||||
|
@ -106,7 +108,8 @@ class RealAddSitePresenter @Inject constructor(
|
|||
url: String,
|
||||
checkInterval: Long,
|
||||
validationMode: ValidationMode,
|
||||
validationContent: String?
|
||||
validationContent: String?,
|
||||
networkTimeout: Int
|
||||
) {
|
||||
val inputErrors = InputErrors()
|
||||
|
||||
|
@ -126,6 +129,9 @@ class RealAddSitePresenter @Inject constructor(
|
|||
} else if (validationMode == JAVASCRIPT && validationContent.isNullOrEmpty()) {
|
||||
inputErrors.javaScript = R.string.please_enter_javaScript
|
||||
}
|
||||
if (networkTimeout <= 0) {
|
||||
inputErrors.networkTimeout = R.string.please_enter_networkTimeout
|
||||
}
|
||||
|
||||
if (inputErrors.any()) {
|
||||
view?.setInputErrors(inputErrors)
|
||||
|
@ -138,7 +144,8 @@ class RealAddSitePresenter @Inject constructor(
|
|||
status = WAITING,
|
||||
checkInterval = checkInterval,
|
||||
validationMode = validationMode,
|
||||
validationContent = validationContent
|
||||
validationContent = validationContent,
|
||||
networkTimeout = networkTimeout
|
||||
)
|
||||
|
||||
with(view!!) {
|
||||
|
|
|
@ -33,6 +33,7 @@ import com.afollestad.nocknock.viewcomponents.ext.dimenFloat
|
|||
import com.afollestad.nocknock.viewcomponents.ext.onItemSelected
|
||||
import com.afollestad.nocknock.viewcomponents.ext.onScroll
|
||||
import com.afollestad.nocknock.viewcomponents.ext.showOrHide
|
||||
import com.afollestad.nocknock.viewcomponents.ext.textAsInt
|
||||
import com.afollestad.nocknock.viewcomponents.ext.trimmedText
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.checkIntervalLayout
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.disableChecksButton
|
||||
|
@ -41,6 +42,7 @@ import kotlinx.android.synthetic.main.activity_viewsite.iconStatus
|
|||
import kotlinx.android.synthetic.main.activity_viewsite.inputName
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.inputUrl
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.loadingProgress
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.responseTimeoutInput
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.responseValidationMode
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.responseValidationSearchTerm
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.rootView
|
||||
|
@ -113,13 +115,15 @@ class ViewSiteActivity : AppCompatActivity(), ViewSiteView {
|
|||
val checkInterval = checkIntervalLayout.getSelectedCheckInterval()
|
||||
val validationMode =
|
||||
responseValidationMode.selectedItemPosition.indexToValidationMode()
|
||||
val defaultTimeout = getString(R.string.response_timeout_default).toInt()
|
||||
|
||||
presenter.commit(
|
||||
name = inputName.trimmedText(),
|
||||
url = inputUrl.trimmedText(),
|
||||
checkInterval = checkInterval,
|
||||
validationMode = validationMode,
|
||||
validationContent = validationMode.validationContent()
|
||||
validationContent = validationMode.validationContent(),
|
||||
networkTimeout = responseTimeoutInput.textAsInt(defaultValue = defaultTimeout)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -189,6 +193,8 @@ class ViewSiteActivity : AppCompatActivity(), ViewSiteView {
|
|||
}
|
||||
}
|
||||
|
||||
responseTimeoutInput.setText(model.networkTimeout.toString())
|
||||
|
||||
disableChecksButton.showOrHide(!this.disabled)
|
||||
doneBtn.setText(
|
||||
if (this.disabled) R.string.renable_and_save_changes
|
||||
|
@ -228,6 +234,11 @@ class ViewSiteActivity : AppCompatActivity(), ViewSiteView {
|
|||
null
|
||||
}
|
||||
)
|
||||
responseTimeoutInput.error = if (errors.networkTimeout != null) {
|
||||
getString(errors.networkTimeout!!)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun scopeWhileAttached(
|
||||
|
|
|
@ -34,11 +34,12 @@ data class InputErrors(
|
|||
var url: Int? = null,
|
||||
var checkInterval: Int? = null,
|
||||
var termSearch: Int? = null,
|
||||
var javaScript: Int? = null
|
||||
var javaScript: Int? = null,
|
||||
var networkTimeout: Int? = null
|
||||
) {
|
||||
@CheckResult fun any(): Boolean {
|
||||
return name != null || url != null || checkInterval != null ||
|
||||
termSearch != null || javaScript != null
|
||||
termSearch != null || javaScript != null || networkTimeout != null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +67,8 @@ interface ViewSitePresenter {
|
|||
url: String,
|
||||
checkInterval: Long,
|
||||
validationMode: ValidationMode,
|
||||
validationContent: String?
|
||||
validationContent: String?,
|
||||
networkTimeout: Int
|
||||
)
|
||||
|
||||
fun checkNow()
|
||||
|
@ -151,7 +153,8 @@ class RealViewSitePresenter @Inject constructor(
|
|||
url: String,
|
||||
checkInterval: Long,
|
||||
validationMode: ValidationMode,
|
||||
validationContent: String?
|
||||
validationContent: String?,
|
||||
networkTimeout: Int
|
||||
) {
|
||||
val inputErrors = InputErrors()
|
||||
|
||||
|
@ -171,6 +174,9 @@ class RealViewSitePresenter @Inject constructor(
|
|||
} else if (validationMode == JAVASCRIPT && validationContent.isNullOrEmpty()) {
|
||||
inputErrors.javaScript = R.string.please_enter_javaScript
|
||||
}
|
||||
if (networkTimeout <= 0) {
|
||||
inputErrors.networkTimeout = R.string.please_enter_networkTimeout
|
||||
}
|
||||
|
||||
if (inputErrors.any()) {
|
||||
view?.setInputErrors(inputErrors)
|
||||
|
@ -184,7 +190,8 @@ class RealViewSitePresenter @Inject constructor(
|
|||
checkInterval = checkInterval,
|
||||
validationMode = validationMode,
|
||||
validationContent = validationContent,
|
||||
disabled = false
|
||||
disabled = false,
|
||||
networkTimeout = networkTimeout
|
||||
)
|
||||
|
||||
with(view!!) {
|
||||
|
|
|
@ -100,6 +100,28 @@
|
|||
android:layout_marginTop="@dimen/content_inset"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/content_inset"
|
||||
android:text="@string/response_timeout"
|
||||
style="@style/NockText.SectionHeader"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/responseTimeoutInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="-4dp"
|
||||
android:layout_marginStart="-4dp"
|
||||
android:hint="@string/response_timeout_default"
|
||||
android:inputType="number"
|
||||
android:maxLength="8"
|
||||
android:textColor="#FFFFFF"
|
||||
tools:ignore="Autofill,HardcodedText,LabelFor"
|
||||
style="@style/NockText.Body.Light"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/responseValidationLabel"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -122,6 +122,28 @@
|
|||
android:layout_marginTop="@dimen/content_inset"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/content_inset"
|
||||
android:text="@string/response_timeout"
|
||||
style="@style/NockText.SectionHeader"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/responseTimeoutInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="-4dp"
|
||||
android:layout_marginStart="-4dp"
|
||||
android:hint="@string/response_timeout_default"
|
||||
android:inputType="number"
|
||||
android:maxLength="8"
|
||||
android:textColor="#FFFFFF"
|
||||
tools:ignore="Autofill,HardcodedText,LabelFor"
|
||||
style="@style/NockText.Body.Light"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<string name="please_enter_check_interval">Please input a check interval.</string>
|
||||
<string name="please_enter_search_term">Please input a search term.</string>
|
||||
<string name="please_enter_javaScript">Please input a validation script.</string>
|
||||
<string name="please_enter_networkTimeout">Please enter a network timeout greater than 0.</string>
|
||||
|
||||
<string name="options">Options</string>
|
||||
<string name="already_checking_sites">Already checking sites!</string>
|
||||
|
@ -49,6 +50,9 @@
|
|||
<string name="disable">Disable</string>
|
||||
<string name="renable_and_save_changes">Enable Checks & Save Changes</string>
|
||||
|
||||
<string name="response_timeout">Network Response Timeout</string>
|
||||
<string name="response_timeout_default">10000</string>
|
||||
|
||||
<string name="refresh_status">Refresh Status</string>
|
||||
|
||||
<string name="warning_http_url">
|
||||
|
|
|
@ -113,7 +113,8 @@ class AddSitePresenterTest {
|
|||
"https://test.com",
|
||||
1,
|
||||
STATUS_CODE,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -131,7 +132,8 @@ class AddSitePresenterTest {
|
|||
"",
|
||||
1,
|
||||
STATUS_CODE,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -149,7 +151,8 @@ class AddSitePresenterTest {
|
|||
"ftp://hello.com",
|
||||
1,
|
||||
STATUS_CODE,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -167,7 +170,8 @@ class AddSitePresenterTest {
|
|||
"https://hello.com",
|
||||
-1,
|
||||
STATUS_CODE,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -185,7 +189,8 @@ class AddSitePresenterTest {
|
|||
"https://hello.com",
|
||||
1,
|
||||
TERM_SEARCH,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -197,13 +202,33 @@ class AddSitePresenterTest {
|
|||
assertThat(errors.termSearch).isEqualTo(R.string.please_enter_search_term)
|
||||
}
|
||||
|
||||
@Test fun commit_networkTimeout_error() {
|
||||
presenter.commit(
|
||||
"Testing",
|
||||
"https://hello.com",
|
||||
1,
|
||||
STATUS_CODE,
|
||||
null,
|
||||
0
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
verify(view).setInputErrors(inputErrorsCaptor.capture())
|
||||
verify(checkStatusManager, never())
|
||||
.scheduleCheck(any(), any(), any(), any())
|
||||
|
||||
val errors = inputErrorsCaptor.firstValue
|
||||
assertThat(errors.networkTimeout).isEqualTo(R.string.please_enter_networkTimeout)
|
||||
}
|
||||
|
||||
@Test fun commit_javaScript_error() {
|
||||
presenter.commit(
|
||||
"Testing",
|
||||
"https://hello.com",
|
||||
1,
|
||||
JAVASCRIPT,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -221,7 +246,8 @@ class AddSitePresenterTest {
|
|||
"https://hello.com",
|
||||
1,
|
||||
STATUS_CODE,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val modelCaptor = argumentCaptor<ServerModel>()
|
||||
|
|
|
@ -156,7 +156,8 @@ class ViewSitePresenterTest {
|
|||
"https://test.com",
|
||||
1,
|
||||
STATUS_CODE,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -174,7 +175,8 @@ class ViewSitePresenterTest {
|
|||
"",
|
||||
1,
|
||||
STATUS_CODE,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -192,7 +194,8 @@ class ViewSitePresenterTest {
|
|||
"ftp://hello.com",
|
||||
1,
|
||||
STATUS_CODE,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -210,7 +213,8 @@ class ViewSitePresenterTest {
|
|||
"https://hello.com",
|
||||
-1,
|
||||
STATUS_CODE,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -228,7 +232,8 @@ class ViewSitePresenterTest {
|
|||
"https://hello.com",
|
||||
1,
|
||||
TERM_SEARCH,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -246,7 +251,8 @@ class ViewSitePresenterTest {
|
|||
"https://hello.com",
|
||||
1,
|
||||
JAVASCRIPT,
|
||||
null
|
||||
null,
|
||||
60000
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
|
@ -258,6 +264,25 @@ class ViewSitePresenterTest {
|
|||
assertThat(errors.javaScript).isEqualTo(R.string.please_enter_javaScript)
|
||||
}
|
||||
|
||||
@Test fun commit_networkTimeout_error() {
|
||||
presenter.commit(
|
||||
"Testing",
|
||||
"https://hello.com",
|
||||
1,
|
||||
STATUS_CODE,
|
||||
null,
|
||||
0
|
||||
)
|
||||
|
||||
val inputErrorsCaptor = argumentCaptor<InputErrors>()
|
||||
verify(view).setInputErrors(inputErrorsCaptor.capture())
|
||||
verify(checkStatusManager, never())
|
||||
.scheduleCheck(any(), any(), any(), any())
|
||||
|
||||
val errors = inputErrorsCaptor.firstValue
|
||||
assertThat(errors.networkTimeout).isEqualTo(R.string.please_enter_networkTimeout)
|
||||
}
|
||||
|
||||
@Test fun commit_success() = runBlocking {
|
||||
val name = "Testing"
|
||||
val url = "https://hello.com"
|
||||
|
@ -274,7 +299,8 @@ class ViewSitePresenterTest {
|
|||
url,
|
||||
checkInterval,
|
||||
validationMode,
|
||||
validationContent
|
||||
validationContent,
|
||||
60000
|
||||
)
|
||||
|
||||
val modelCaptor = argumentCaptor<ServerModel>()
|
||||
|
@ -358,4 +384,4 @@ class ViewSitePresenterTest {
|
|||
on { getAction() } doReturn action
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@ data class ServerModel(
|
|||
val reason: String? = null,
|
||||
val validationMode: ValidationMode,
|
||||
val validationContent: String? = null,
|
||||
val disabled: Boolean = false
|
||||
val disabled: Boolean = false,
|
||||
val networkTimeout: Int = 0
|
||||
) : IdProvider {
|
||||
|
||||
companion object {
|
||||
|
@ -42,6 +43,7 @@ data class ServerModel(
|
|||
const val COLUMN_VALIDATION_MODE = "validation_mode"
|
||||
const val COLUMN_VALIDATION_CONTENT = "validation_content"
|
||||
const val COLUMN_DISABLED = "disabled"
|
||||
const val COLUMN_NETWORK_TIMEOUT = "network_timeout"
|
||||
|
||||
const val DEFAULT_SORT_ORDER = "$COLUMN_NAME ASC, $COLUMN_DISABLED DESC"
|
||||
|
||||
|
@ -58,7 +60,8 @@ data class ServerModel(
|
|||
cursor.getColumnIndex(COLUMN_VALIDATION_MODE)
|
||||
).toValidationMode(),
|
||||
validationContent = cursor.getString(cursor.getColumnIndex(COLUMN_VALIDATION_CONTENT)),
|
||||
disabled = cursor.getInt(cursor.getColumnIndex(COLUMN_DISABLED)) == 1
|
||||
disabled = cursor.getInt(cursor.getColumnIndex(COLUMN_DISABLED)) == 1,
|
||||
networkTimeout = cursor.getInt(cursor.getColumnIndex(COLUMN_NETWORK_TIMEOUT))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -81,5 +84,6 @@ data class ServerModel(
|
|||
put(COLUMN_VALIDATION_MODE, validationMode.value)
|
||||
put(COLUMN_VALIDATION_CONTENT, validationContent)
|
||||
put(COLUMN_DISABLED, disabled)
|
||||
put(COLUMN_NETWORK_TIMEOUT, networkTimeout)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@ private const val SQL_CREATE_ENTRIES =
|
|||
"${ServerModel.COLUMN_REASON} TEXT," +
|
||||
"${ServerModel.COLUMN_VALIDATION_MODE} INTEGER," +
|
||||
"${ServerModel.COLUMN_VALIDATION_CONTENT} TEXT," +
|
||||
"${ServerModel.COLUMN_DISABLED} INTEGER)"
|
||||
"${ServerModel.COLUMN_DISABLED} INTEGER," +
|
||||
"${ServerModel.COLUMN_NETWORK_TIMEOUT} INTEGER" +
|
||||
")"
|
||||
|
||||
private const val SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS ${ServerModel.TABLE_NAME}"
|
||||
|
||||
|
@ -30,7 +32,7 @@ class ServerModelDbHelper(context: Context) : SQLiteOpenHelper(
|
|||
context, DATABASE_NAME, null, DATABASE_VERSION
|
||||
) {
|
||||
companion object {
|
||||
const val DATABASE_VERSION = 2
|
||||
const val DATABASE_VERSION = 3
|
||||
const val DATABASE_NAME = "ServerModels.db"
|
||||
}
|
||||
|
||||
|
@ -43,8 +45,12 @@ class ServerModelDbHelper(context: Context) : SQLiteOpenHelper(
|
|||
oldVersion: Int,
|
||||
newVersion: Int
|
||||
) {
|
||||
db.execSQL(SQL_DELETE_ENTRIES)
|
||||
onCreate(db)
|
||||
if (newVersion == 3 && oldVersion == 2) {
|
||||
db.execSQL(
|
||||
"ALTER TABLE ${ServerModel.TABLE_NAME} " +
|
||||
"ADD COLUMN ${ServerModel.COLUMN_NETWORK_TIMEOUT} INTEGER DEFAULT 10000"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDowngrade(
|
||||
|
|
|
@ -19,7 +19,9 @@ import com.afollestad.nocknock.utilities.providers.StringProvider
|
|||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import java.net.SocketTimeoutException
|
||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
import javax.inject.Inject
|
||||
import timber.log.Timber.d as log
|
||||
|
||||
|
@ -29,6 +31,8 @@ data class CheckResult(
|
|||
val response: Response? = null
|
||||
)
|
||||
|
||||
typealias ClientTimeoutChanger = (client: OkHttpClient, timeout: Int) -> OkHttpClient
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
interface CheckStatusManager {
|
||||
|
||||
|
@ -55,6 +59,12 @@ class RealCheckStatusManager @Inject constructor(
|
|||
private val siteStore: ServerModelStore
|
||||
) : CheckStatusManager {
|
||||
|
||||
private var clientTimeoutChanger: ClientTimeoutChanger = { client, timeout ->
|
||||
client.newBuilder()
|
||||
.callTimeout(timeout.toLong(), MILLISECONDS)
|
||||
.build()
|
||||
}
|
||||
|
||||
override suspend fun ensureScheduledChecks() {
|
||||
val sites = siteStore.get()
|
||||
if (sites.isEmpty()) {
|
||||
|
@ -121,6 +131,7 @@ class RealCheckStatusManager @Inject constructor(
|
|||
|
||||
override suspend fun performCheck(site: ServerModel): CheckResult {
|
||||
check(site.id != 0) { "Cannot schedule checks for jobs with no ID." }
|
||||
check(site.networkTimeout > 0) { "Network timeout not set for site ${site.id}" }
|
||||
log("performCheck(${site.id}) - GET ${site.url}")
|
||||
|
||||
val request = Request.Builder()
|
||||
|
@ -129,8 +140,10 @@ class RealCheckStatusManager @Inject constructor(
|
|||
.build()
|
||||
|
||||
return try {
|
||||
val response = okHttpClient.newCall(request)
|
||||
val client = clientTimeoutChanger(okHttpClient, site.networkTimeout)
|
||||
val response = client.newCall(request)
|
||||
.execute()
|
||||
|
||||
if (response.isSuccessful || response.code() == 401) {
|
||||
log("performCheck(${site.id}) = Successful")
|
||||
CheckResult(
|
||||
|
@ -164,4 +177,8 @@ class RealCheckStatusManager @Inject constructor(
|
|||
private fun jobForSite(site: ServerModel) =
|
||||
jobScheduler.allPendingJobs
|
||||
.firstOrNull { job -> job.id == site.id }
|
||||
|
||||
@TestOnly fun setClientTimeoutChanger(changer: ClientTimeoutChanger) {
|
||||
this.clientTimeoutChanger = changer
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,12 @@ class CheckStatusManagerTest {
|
|||
bundleProvider,
|
||||
jobInfoProvider,
|
||||
store
|
||||
)
|
||||
).apply {
|
||||
setClientTimeoutChanger { _, timeout ->
|
||||
whenever(okHttpClient.callTimeoutMillis()).doReturn(timeout)
|
||||
return@setClientTimeoutChanger okHttpClient
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun ensureScheduledChecks_noEnabledSites() = runBlocking {
|
||||
val model1 = fakeModel().copy(disabled = true)
|
||||
|
@ -234,6 +239,8 @@ class CheckStatusManagerTest {
|
|||
reason = null
|
||||
)
|
||||
)
|
||||
assertThat(okHttpClient.callTimeoutMillis())
|
||||
.isEqualTo(model1.networkTimeout)
|
||||
}
|
||||
|
||||
@Test fun performCheck_401_butStillSuccess() = runBlocking {
|
||||
|
@ -280,7 +287,8 @@ class CheckStatusManagerTest {
|
|||
id = 1,
|
||||
name = "Wakanda Forever",
|
||||
url = "https://www.wakanda.gov",
|
||||
validationMode = STATUS_CODE
|
||||
validationMode = STATUS_CODE,
|
||||
networkTimeout = 60000
|
||||
)
|
||||
|
||||
private fun fakeJob(id: Int): JobInfo {
|
||||
|
|
|
@ -24,7 +24,13 @@ fun Long.timeString() = when {
|
|||
"${ceil((this.toFloat() / DAY.toFloat()).toDouble()).toInt()}d"
|
||||
this >= HOUR ->
|
||||
"${ceil((this.toFloat() / HOUR.toFloat()).toDouble()).toInt()}h"
|
||||
this >= MINUTE ->
|
||||
"${ceil((this.toFloat() / MINUTE.toFloat()).toDouble()).toInt()}m"
|
||||
this >= MINUTE -> {
|
||||
val result = "${ceil((this.toFloat() / MINUTE.toFloat()).toDouble()).toInt()}m"
|
||||
if (result == "60m") {
|
||||
"1h"
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
else -> "<1m"
|
||||
}
|
||||
|
|
|
@ -9,9 +9,14 @@ import android.widget.TextView
|
|||
|
||||
fun TextView.trimmedText() = text.toString().trim()
|
||||
|
||||
fun TextView.textAsLong(): Long {
|
||||
fun TextView.textAsInt(defaultValue: Int = 0): Int {
|
||||
val text = trimmedText()
|
||||
return if (text.isEmpty()) 0L else text.toLong()
|
||||
return if (text.isEmpty()) defaultValue else text.toInt()
|
||||
}
|
||||
|
||||
fun TextView.textAsLong(defaultValue: Long = 0L): Long {
|
||||
val text = trimmedText()
|
||||
return if (text.isEmpty()) defaultValue else text.toLong()
|
||||
}
|
||||
|
||||
///** @author https://stackoverflow.com/a/53296137/309644 */
|
||||
|
|
Loading…
Add table
Reference in a new issue