Skip to content

Commit c486f18

Browse files
authored
Merge pull request #131 from CrisisCleanup/bug-fixes
Bug fixes
2 parents 7a89730 + 3a074f6 commit c486f18

File tree

14 files changed

+179
-36
lines changed

14 files changed

+179
-36
lines changed

app/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ plugins {
1414

1515
android {
1616
defaultConfig {
17-
val buildVersion = 242
17+
val buildVersion = 246
1818
applicationId = "com.crisiscleanup"
1919
versionCode = buildVersion
2020
versionName = "0.9.${buildVersion - 168}"

app/src/main/java/com/crisiscleanup/network/CrisisCleanupInterceptorProvider.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import okhttp3.Response
2929
import okhttp3.ResponseBody
3030
import okhttp3.ResponseBody.Companion.toResponseBody
3131
import java.io.IOException
32+
import java.util.concurrent.TimeUnit
3233
import javax.inject.Inject
3334
import javax.inject.Singleton
3435

@@ -75,6 +76,19 @@ class CrisisCleanupInterceptorProvider @Inject constructor(
7576
key: RequestHeaderKey,
7677
) = headerKeysLookup.getHeaderKeys(request)?.get(key)
7778

79+
private fun getHeaderTimeout(
80+
request: Request,
81+
key: RequestHeaderKey,
82+
) = getHeaderKey(request, key)
83+
?.toIntOrNull()
84+
?.let { timeout ->
85+
if (timeout > 1) {
86+
timeout
87+
} else {
88+
null
89+
}
90+
}
91+
7892
private val headerInterceptor by lazy {
7993
Interceptor { chain ->
8094
var request = chain.request()
@@ -178,6 +192,26 @@ class CrisisCleanupInterceptorProvider @Inject constructor(
178192
return nextResponse
179193
}
180194

195+
private val customTimeoutInterceptor by lazy {
196+
Interceptor { chain ->
197+
val request = chain.request()
198+
var timeoutChain = chain
199+
200+
getHeaderTimeout(request, RequestHeaderKey.ConnectTimeout)?.let { timeout ->
201+
timeoutChain = timeoutChain.withConnectTimeout(timeout, TimeUnit.SECONDS)
202+
}
203+
204+
getHeaderTimeout(request, RequestHeaderKey.ReadTimeout)?.let { timeout ->
205+
timeoutChain = timeoutChain.withReadTimeout(timeout, TimeUnit.SECONDS)
206+
}
207+
208+
val connectTimeout = timeoutChain.connectTimeoutMillis()
209+
val readTimeout = timeoutChain.readTimeoutMillis()
210+
211+
timeoutChain.proceed(request)
212+
}
213+
}
214+
181215
private val wrapResponseInterceptor by lazy {
182216
Interceptor { chain ->
183217
val request = chain.request()
@@ -237,6 +271,7 @@ class CrisisCleanupInterceptorProvider @Inject constructor(
237271

238272
override val interceptors: List<Interceptor> = listOf(
239273
headerInterceptor,
274+
customTimeoutInterceptor,
240275
wrapResponseInterceptor,
241276
clientErrorInterceptor,
242277
serverErrorInterceptor,

core/mapmarker/src/main/java/com/crisiscleanup/core/mapmarker/model/MapViewCameraUpdate.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ data class MapViewCameraZoom(
4040
val center: LatLng,
4141
val zoom: Float = 8f,
4242
val durationMs: Int = 500,
43+
val timestamp: Instant = Clock.System.now(),
4344
private val initialApply: Boolean = true,
4445
) {
4546
private val applyToMap = AtomicBoolean(initialApply)

core/network/src/main/java/com/crisiscleanup/core/network/di/NetworkModule.kt

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import coil.decode.SvgDecoder
66
import coil.disk.DiskCache
77
import coil.util.DebugLogger
88
import com.crisiscleanup.core.common.AppEnv
9+
import com.crisiscleanup.core.common.AppSettingsProvider
910
import com.crisiscleanup.core.network.AuthInterceptorProvider
10-
import com.crisiscleanup.core.network.BuildConfig
1111
import com.crisiscleanup.core.network.CrisisCleanupAccountApi
1212
import com.crisiscleanup.core.network.CrisisCleanupAuthApi
1313
import com.crisiscleanup.core.network.CrisisCleanupNetworkDataSource
@@ -88,45 +88,69 @@ object NetworkModule {
8888
@Provides
8989
@Singleton
9090
fun providesCrisisCleanupAuthRetrofit(
91+
appEnv: AppEnv,
92+
settingsProvider: AppSettingsProvider,
9193
interceptorProvider: AuthInterceptorProvider,
9294
json: Json,
93-
appEnv: AppEnv,
9495
): Retrofit {
9596
val interceptors = listOf(interceptorProvider.clientErrorInterceptor)
96-
return getCrisisCleanupApiBuilder(interceptors, json, appEnv)
97+
return getCrisisCleanupApiBuilder(
98+
appEnv,
99+
settingsProvider,
100+
interceptors,
101+
json,
102+
)
97103
}
98104

99105
@RetrofitConfiguration(RetrofitConfigurations.CrisisCleanup)
100106
@Provides
101107
@Singleton
102108
fun providesCrisisCleanupRetrofit(
109+
appEnv: AppEnv,
110+
settingsProvider: AppSettingsProvider,
103111
interceptorProvider: RetrofitInterceptorProvider,
104112
headerKeysLookup: RequestHeaderKeysLookup,
105113
json: Json,
106-
appEnv: AppEnv,
107-
) = getCrisisCleanupApiBuilder(interceptorProvider, headerKeysLookup, json, appEnv)
114+
) = getCrisisCleanupApiBuilder(
115+
appEnv,
116+
settingsProvider,
117+
interceptorProvider,
118+
headerKeysLookup,
119+
json,
120+
)
108121

109122
@RetrofitConfiguration(RetrofitConfigurations.Basic)
110123
@Provides
111124
@Singleton
112125
fun providesBasicRetrofit(
113-
interceptorProvider: RetrofitInterceptorProvider,
114126
appEnv: AppEnv,
127+
settingsProvider: AppSettingsProvider,
128+
interceptorProvider: RetrofitInterceptorProvider,
115129
): Retrofit {
116130
val interceptors = listOf(interceptorProvider.serverErrorInterceptor)
117-
return getApiBuilder(interceptors, appEnv)
131+
return getApiBuilder(
132+
appEnv,
133+
settingsProvider,
134+
interceptors,
135+
)
118136
}
119137

120138
@RetrofitConfiguration(RetrofitConfigurations.BasicJson)
121139
@Provides
122140
@Singleton
123141
fun providesBasicJsonRetrofit(
124-
interceptorProvider: RetrofitInterceptorProvider,
125142
appEnv: AppEnv,
143+
settingsProvider: AppSettingsProvider,
144+
interceptorProvider: RetrofitInterceptorProvider,
126145
json: Json,
127146
): Retrofit {
128147
val interceptors = listOf(interceptorProvider.serverErrorInterceptor)
129-
return getJsonApiBuilder(interceptors, appEnv, json)
148+
return getJsonApiBuilder(
149+
appEnv,
150+
settingsProvider,
151+
interceptors,
152+
json,
153+
)
130154
}
131155

132156
/**
@@ -155,7 +179,7 @@ object NetworkModule {
155179
// but some problematic images are fetching each time
156180
.respectCacheHeaders(false)
157181
.apply {
158-
if (BuildConfig.DEBUG) {
182+
if (appEnv.isDebuggable) {
159183
val callFactory = OkHttpClient.Builder()
160184
.addInterceptor(
161185
HttpLoggingInterceptor()

core/network/src/main/java/com/crisiscleanup/core/network/retrofit/DataApiClient.kt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ private interface DataSourceApi {
7373
ordering: String,
7474
@Query("start_at__gt")
7575
after: Instant?,
76+
@Tag endpointId: EndpointRequestId = EndpointRequestId.Incidents,
7677
): NetworkIncidentsResult
7778

7879
@GET("incidents")
@@ -85,10 +86,7 @@ private interface DataSourceApi {
8586
ordering: String,
8687
@Query("start_at__gt")
8788
after: Instant?,
88-
// Differentiates this endpoint call from getIncidents above
89-
// when determining header keys (locally)
90-
@Query("_ignore")
91-
callerTag: String = "_no-auth",
89+
@Tag endpointId: EndpointRequestId = EndpointRequestId.IncidentsNoAuth,
9290
): NetworkIncidentsResult
9391

9492
@GET("incidents_list")
@@ -173,6 +171,17 @@ private interface DataSourceApi {
173171
suspend fun getWorksites(
174172
@Query("id__in", encoded = true)
175173
worksiteIds: String,
174+
@Tag endpointId: EndpointRequestId = EndpointRequestId.Worksites,
175+
): NetworkWorksitesFullResult
176+
177+
@TokenAuthenticationHeader
178+
@ConnectTimeoutHeader("10")
179+
@ReadTimeoutHeader("15")
180+
@GET("worksites")
181+
suspend fun getWorksite(
182+
@Query("id__in")
183+
worksiteId: String,
184+
@Tag endpointId: EndpointRequestId = EndpointRequestId.Worksite,
176185
): NetworkWorksitesFullResult
177186

178187
@TokenAuthenticationHeader
@@ -242,6 +251,8 @@ private interface DataSourceApi {
242251
): NetworkCountResult
243252

244253
@TokenAuthenticationHeader
254+
@ConnectTimeoutHeader("10")
255+
@ReadTimeoutHeader("15")
245256
@GET("worksite_requests")
246257
suspend fun getWorkTypeRequests(
247258
@Query("worksite_work_type__worksite")
@@ -457,7 +468,9 @@ class DataApiClient @Inject constructor(
457468
.apply { errors?.tryThrowException() }
458469
.results
459470

460-
override suspend fun getWorksite(id: Long) = getWorksites(listOf(id))?.firstOrNull()
471+
override suspend fun getWorksite(id: Long) = networkApi.getWorksite(id.toString())
472+
.apply { errors?.tryThrowException() }
473+
.results?.firstOrNull()
461474

462475
override suspend fun getWorksitesCount(incidentId: Long, updatedAtAfter: Instant?) =
463476
networkApi.getWorksitesCount(incidentId, updatedAtAfter)

core/network/src/main/java/com/crisiscleanup/core/network/retrofit/RequestHeaderCallAdapterFactory.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@ import java.lang.reflect.Type
88

99
enum class RequestHeaderKey {
1010
AccessTokenAuth,
11+
ConnectTimeout,
12+
ReadTimeout,
1113
WrapResponse,
1214
ThrowClientError,
1315
}
1416

1517
enum class EndpointRequestId {
1618
MyProfile,
1719
MyProfileNoAuth,
20+
Incidents,
21+
IncidentsNoAuth,
22+
Worksites,
23+
Worksite,
1824
}
1925

2026
class RequestHeaderKeysLookup(
@@ -60,6 +66,14 @@ class RequestHeaderKeysLookup(
6066
TokenAuthenticationHeader::class ->
6167
requestKeys[RequestHeaderKey.AccessTokenAuth] = ""
6268

69+
ConnectTimeoutHeader::class ->
70+
requestKeys[RequestHeaderKey.ConnectTimeout] =
71+
(it as ConnectTimeoutHeader).timeoutSeconds
72+
73+
ReadTimeoutHeader::class ->
74+
requestKeys[RequestHeaderKey.ReadTimeout] =
75+
(it as ReadTimeoutHeader).timeoutSeconds
76+
6377
WrapResponseHeader::class ->
6478
requestKeys[RequestHeaderKey.WrapResponse] = (it as WrapResponseHeader).key
6579

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.crisiscleanup.core.network.retrofit
2+
3+
import kotlin.annotation.AnnotationRetention.RUNTIME
4+
import kotlin.annotation.AnnotationTarget.FUNCTION
5+
6+
@Target(FUNCTION)
7+
@Retention(RUNTIME)
8+
internal annotation class ConnectTimeoutHeader(val timeoutSeconds: String)
9+
10+
@Target(FUNCTION)
11+
@Retention(RUNTIME)
12+
internal annotation class ReadTimeoutHeader(val timeoutSeconds: String)

core/network/src/main/java/com/crisiscleanup/core/network/retrofit/RetrofitApiBuilders.kt

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.crisiscleanup.core.network.retrofit
22

33
import com.crisiscleanup.core.common.AppEnv
4-
import com.crisiscleanup.core.network.BuildConfig
4+
import com.crisiscleanup.core.common.AppSettingsProvider
55
import com.crisiscleanup.core.network.RetrofitInterceptorProvider
66
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
77
import kotlinx.serialization.json.Json
@@ -14,8 +14,6 @@ import retrofit2.Retrofit
1414
import java.util.concurrent.TimeUnit
1515
import javax.inject.Qualifier
1616

17-
private const val CRISIS_CLEANUP_API_BASE_URL = BuildConfig.API_BASE_URL
18-
1917
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER)
2018
@Qualifier
2119
@Retention(AnnotationRetention.BINARY)
@@ -50,9 +48,10 @@ private val Json.converterFactory: Converter.Factory
5048
get() = asConverterFactory("application/json".toMediaType())
5149

5250
internal fun getCrisisCleanupApiBuilder(
51+
appEnv: AppEnv,
52+
settingsProvider: AppSettingsProvider,
5353
interceptors: Collection<Interceptor>,
5454
networkApiJson: Json,
55-
appEnv: AppEnv,
5655
): Retrofit {
5756
val clientBuilder = getClientBuilder(appEnv.isDebuggable)
5857

@@ -61,17 +60,18 @@ internal fun getCrisisCleanupApiBuilder(
6160
}
6261

6362
return Retrofit.Builder()
64-
.baseUrl(CRISIS_CLEANUP_API_BASE_URL)
63+
.baseUrl(settingsProvider.apiBaseUrl)
6564
.client(clientBuilder.build())
6665
.addConverterFactory(networkApiJson.converterFactory)
6766
.build()
6867
}
6968

7069
internal fun getCrisisCleanupApiBuilder(
70+
appEnv: AppEnv,
71+
settingsProvider: AppSettingsProvider,
7172
interceptorProvider: RetrofitInterceptorProvider,
7273
headerKeysLookup: RequestHeaderKeysLookup,
7374
networkApiJson: Json,
74-
appEnv: AppEnv,
7575
): Retrofit {
7676
val clientBuilder = getClientBuilder(appEnv.isDebuggable)
7777

@@ -80,16 +80,17 @@ internal fun getCrisisCleanupApiBuilder(
8080
}
8181

8282
return Retrofit.Builder()
83-
.baseUrl(CRISIS_CLEANUP_API_BASE_URL)
83+
.baseUrl(settingsProvider.apiBaseUrl)
8484
.client(clientBuilder.build())
8585
.addCallAdapterFactory(RequestHeaderCallAdapterFactory(headerKeysLookup))
8686
.addConverterFactory(networkApiJson.converterFactory)
8787
.build()
8888
}
8989

9090
internal fun getApiBuilder(
91-
interceptors: List<Interceptor>,
9291
appEnv: AppEnv,
92+
settingsProvider: AppSettingsProvider,
93+
interceptors: List<Interceptor>,
9394
): Retrofit {
9495
val clientBuilder = getClientBuilder(appEnv.isDebuggable)
9596

@@ -98,14 +99,15 @@ internal fun getApiBuilder(
9899
}
99100

100101
return Retrofit.Builder()
101-
.baseUrl(CRISIS_CLEANUP_API_BASE_URL)
102+
.baseUrl(settingsProvider.apiBaseUrl)
102103
.client(clientBuilder.build())
103104
.build()
104105
}
105106

106107
internal fun getJsonApiBuilder(
107-
interceptors: List<Interceptor>,
108108
appEnv: AppEnv,
109+
settingsProvider: AppSettingsProvider,
110+
interceptors: List<Interceptor>,
109111
networkApiJson: Json,
110112
): Retrofit {
111113
val clientBuilder = getClientBuilder(appEnv.isDebuggable)
@@ -115,7 +117,7 @@ internal fun getJsonApiBuilder(
115117
}
116118

117119
return Retrofit.Builder()
118-
.baseUrl(CRISIS_CLEANUP_API_BASE_URL)
120+
.baseUrl(settingsProvider.apiBaseUrl)
119121
.client(clientBuilder.build())
120122
.addConverterFactory(networkApiJson.converterFactory)
121123
.build()

0 commit comments

Comments
 (0)