Skip to content

Commit 66ada4c

Browse files
committed
Persist rediscovered xmlRpcUrl via a targeted write
attemptXmlRpcRediscovery dispatched newUpdateSiteAction to change one field, which (with XMLRPC_URL excluded from the full-row mapper) dropped the value and rewrote ~80 unchanged columns. Add SiteStore.persistXmlRpcUrl and route rediscovery through it — one targeted write, mirroring the wpApiRestUrl heal. Drops the now-unused dispatcher from the slice.
1 parent 13fc334 commit 66ada4c

4 files changed

Lines changed: 29 additions & 17 deletions

File tree

WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/applicationpassword/ApplicationPasswordViewModelSlice.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import kotlinx.coroutines.launch
99
import kotlinx.coroutines.withContext
1010
import org.wordpress.android.R
1111
import androidx.annotation.VisibleForTesting
12-
import org.wordpress.android.fluxc.Dispatcher
13-
import org.wordpress.android.fluxc.generated.SiteActionBuilder
1412
import org.wordpress.android.fluxc.model.SiteModel
1513
import org.wordpress.android.fluxc.network.discovery.SelfHostedEndpointFinder
1614
import org.wordpress.android.fluxc.network.xmlrpc.site.SiteXMLRPCClient
@@ -41,7 +39,6 @@ class ApplicationPasswordViewModelSlice @Inject constructor(
4139
private val selfHostedEndpointFinder: SelfHostedEndpointFinder,
4240
private val siteXMLRPCClient: SiteXMLRPCClient,
4341
private val siteApiRestUrlRecoverer: SiteApiRestUrlRecoverer,
44-
private val dispatcher: Dispatcher,
4542
private val credentialsChangedNotifier: CredentialsChangedNotifier,
4643
@Named(IO_THREAD) private val ioDispatcher: CoroutineDispatcher,
4744
) {
@@ -257,9 +254,10 @@ class ApplicationPasswordViewModelSlice @Inject constructor(
257254
}
258255

259256
site.xmlRpcUrl = xmlRpcEndpoint
260-
dispatcher.dispatch(
261-
SiteActionBuilder.newUpdateSiteAction(site)
262-
)
257+
// Persist only the rediscovered column — mirrors healApiRestUrlIfMissing. A full-row
258+
// updateSite would rewrite ~80 columns from this in-memory model for a one-field change
259+
// (risking clobbering other out-of-band values), so write just xmlRpcUrl.
260+
siteStore.persistXmlRpcUrl(site.id, xmlRpcEndpoint)
263261
buildCard(site)
264262
} catch (
265263
@Suppress("SwallowedException")

WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/applicationpassword/ApplicationPasswordViewModelSliceTest.kt

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import org.mockito.kotlin.verify
1919
import org.mockito.kotlin.whenever
2020
import org.wordpress.android.BaseUnitTest
2121
import org.mockito.kotlin.mock
22-
import org.wordpress.android.fluxc.Dispatcher
2322
import org.wordpress.android.fluxc.model.SiteModel
2423
import org.wordpress.android.fluxc.model.SitesModel
2524
import org.wordpress.android.fluxc.network.BaseRequest.BaseNetworkError
@@ -71,9 +70,6 @@ class ApplicationPasswordViewModelSliceTest : BaseUnitTest() {
7170
@Mock
7271
lateinit var siteApiRestUrlRecoverer: SiteApiRestUrlRecoverer
7372

74-
@Mock
75-
lateinit var dispatcher: Dispatcher
76-
7773
@Mock
7874
lateinit var credentialsChangedNotifier: CredentialsChangedNotifier
7975

@@ -96,7 +92,6 @@ class ApplicationPasswordViewModelSliceTest : BaseUnitTest() {
9692
selfHostedEndpointFinder,
9793
siteXMLRPCClient,
9894
siteApiRestUrlRecoverer,
99-
dispatcher,
10095
credentialsChangedNotifier,
10196
testDispatcher()
10297
).apply {
@@ -380,7 +375,7 @@ class ApplicationPasswordViewModelSliceTest : BaseUnitTest() {
380375
}
381376

382377
@Test
383-
fun `given xmlRpc rediscovery and auth check succeed, then update site and dispatch`() =
378+
fun `given xmlRpc rediscovery and auth check succeed, then persist the discovered xmlRpcUrl`() =
384379
runTest {
385380
val xmlRpcUrl = "https://www.test.com/xmlrpc.php"
386381
whenever(
@@ -392,16 +387,17 @@ class ApplicationPasswordViewModelSliceTest : BaseUnitTest() {
392387
eq(xmlRpcUrl), any(), any()
393388
)
394389
).thenReturn(SitesModel(listOf(SiteModel())))
390+
whenever(siteStore.persistXmlRpcUrl(any(), any())).thenReturn(mock())
395391

396392
applicationPasswordViewModelSlice
397393
.attemptXmlRpcRediscovery(siteTest)
398394

399-
verify(dispatcher).dispatch(any())
395+
verify(siteStore).persistXmlRpcUrl(siteTest.id, xmlRpcUrl)
400396
assert(siteTest.xmlRpcUrl == xmlRpcUrl)
401397
}
402398

403399
@Test
404-
fun `given xmlRpc rediscovery succeeds but auth check fails, then do not dispatch`() =
400+
fun `given xmlRpc rediscovery succeeds but auth check fails, then do not persist`() =
405401
runTest {
406402
siteTest.xmlRpcUrl = null
407403
val xmlRpcUrl = "https://www.test.com/xmlrpc.php"
@@ -421,12 +417,12 @@ class ApplicationPasswordViewModelSliceTest : BaseUnitTest() {
421417
applicationPasswordViewModelSlice
422418
.attemptXmlRpcRediscovery(siteTest)
423419

424-
verify(dispatcher, never()).dispatch(any())
420+
verify(siteStore, never()).persistXmlRpcUrl(any(), any())
425421
assert(siteTest.xmlRpcUrl.isNullOrEmpty())
426422
}
427423

428424
@Test
429-
fun `given xmlRpc rediscovery fails, then do not dispatch`() =
425+
fun `given xmlRpc rediscovery fails, then do not persist`() =
430426
runTest {
431427
siteTest.xmlRpcUrl = null
432428
whenever(
@@ -441,7 +437,7 @@ class ApplicationPasswordViewModelSliceTest : BaseUnitTest() {
441437

442438
verify(selfHostedEndpointFinder)
443439
.verifyOrDiscoverXMLRPCEndpoint(TEST_URL)
444-
verify(dispatcher, never()).dispatch(any())
440+
verify(siteStore, never()).persistXmlRpcUrl(any(), any())
445441
assert(siteTest.xmlRpcUrl.isNullOrEmpty())
446442
}
447443
}

libs/fluxc/src/main/java/org/wordpress/android/fluxc/store/SiteStore.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,6 +1691,17 @@ open class SiteStore @Inject constructor(
16911691
}
16921692
}
16931693

1694+
/**
1695+
* Targeted persist for [SiteModel.xmlRpcUrl] — for callers (e.g. XML-RPC rediscovery) that heal/discover
1696+
* only that one column and don't want to full-row write an in-memory model. The generic update path also
1697+
* persists xmlRpcUrl (and preserves it on absence), so this is a convenience for the single-column heal,
1698+
* not the sole writer.
1699+
*/
1700+
suspend fun persistXmlRpcUrl(localId: Int, xmlRpcUrl: String): OnSiteChanged =
1701+
coroutineEngine.withDefaultContext(T.API, this, "persistXmlRpcUrl") {
1702+
OnSiteChanged(siteSqlUtils.updateXmlRpcUrl(localId, xmlRpcUrl))
1703+
}
1704+
16941705
@Suppress("SwallowedException", "TooGenericExceptionCaught")
16951706
private fun updateApplicationPassword(siteModel: SiteModel): OnSiteChanged {
16961707
return try {

libs/fluxc/src/test/java/org/wordpress/android/fluxc/store/SiteStoreTest.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,13 @@ class SiteStoreTest {
647647
verify(siteSqlUtils, never()).clearWpApiRestUrl(8)
648648
}
649649

650+
@Test
651+
fun `persistXmlRpcUrl writes the column via the targeted writer`() = test {
652+
siteStore.persistXmlRpcUrl(9, "https://selfhosted.test/xmlrpc.php")
653+
654+
verify(siteSqlUtils).updateXmlRpcUrl(9, "https://selfhosted.test/xmlrpc.php")
655+
}
656+
650657
@Test
651658
fun `fetchPostFormats returns empty list for WPAPI site without crashing`() =
652659
test {

0 commit comments

Comments
 (0)