Merge branch 'develop' of https://github.com/finocd2la/TSUDesk into feature/schedule
# Conflicts: # feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleApi.kt # feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/domain/model/ScheduleEntity.kt
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
package ru.fincode.tsudesk.core.network
|
||||
|
||||
object NetworkConstants {
|
||||
object Constants {
|
||||
const val BASE_URL = "https://tulsu.ru/schedule/queries/"
|
||||
}
|
||||
@@ -1,24 +1,58 @@
|
||||
package ru.fincode.tsudesk.core.network
|
||||
|
||||
import retrofit2.HttpException
|
||||
import retrofit2.Response
|
||||
import ru.fincode.tsudesk.core.network.model.NetworkError
|
||||
import ru.fincode.tsudesk.core.network.model.NetworkMeta
|
||||
import ru.fincode.tsudesk.core.network.model.NetworkResult
|
||||
import ru.fincode.tsudesk.core.network.model.NetworkResult.Success
|
||||
import java.io.IOException
|
||||
import java.net.SocketTimeoutException
|
||||
|
||||
suspend inline fun <T> safeApiCall(
|
||||
crossinline block: suspend () -> T
|
||||
suspend inline fun <T> apiCall(
|
||||
crossinline block: suspend () -> Response<T>
|
||||
): NetworkResult<T> {
|
||||
val startedAt = System.currentTimeMillis()
|
||||
|
||||
return try {
|
||||
NetworkResult.Success(block())
|
||||
val response = block()
|
||||
val finishedAt = System.currentTimeMillis()
|
||||
|
||||
val raw = response.raw()
|
||||
val meta = NetworkMeta(
|
||||
startedAtMillis = startedAt,
|
||||
finishedAtMillis = finishedAt,
|
||||
sentAtMillis = raw.sentRequestAtMillis,
|
||||
receivedAtMillis = raw.receivedResponseAtMillis
|
||||
)
|
||||
|
||||
if (response.isSuccessful) {
|
||||
val body = response.body()
|
||||
if (body != null) {
|
||||
Success(data = body, meta = meta)
|
||||
} else {
|
||||
NetworkResult.Error(
|
||||
NetworkError.Unknown(
|
||||
throwable = NullPointerException("Response body is null"),
|
||||
meta = meta
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
NetworkResult.Error(NetworkError.Http(code = response.code(), meta = meta))
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
NetworkResult.Error(t.toNetworkError())
|
||||
val meta = NetworkMeta(
|
||||
startedAtMillis = startedAt,
|
||||
finishedAtMillis = System.currentTimeMillis()
|
||||
)
|
||||
NetworkResult.Error(t.toNetworkError(meta))
|
||||
}
|
||||
}
|
||||
|
||||
fun Throwable.toNetworkError(): NetworkError = when (this) {
|
||||
is SocketTimeoutException -> NetworkError.Timeout
|
||||
is IOException -> NetworkError.NoInternet
|
||||
is HttpException -> NetworkError.Http(code())
|
||||
else -> NetworkError.Unknown(this)
|
||||
fun Throwable.toNetworkError(meta: NetworkMeta): NetworkError = when (this) {
|
||||
is SocketTimeoutException -> NetworkError.Timeout(meta)
|
||||
is IOException -> NetworkError.NoInternet(meta)
|
||||
is HttpException -> NetworkError.Http(code(), meta)
|
||||
else -> NetworkError.Unknown(this, meta)
|
||||
}
|
||||
|
||||
@@ -1,40 +1,30 @@
|
||||
package ru.fincode.tsudesk.core.network
|
||||
package ru.fincode.tsudesk.core.network.di
|
||||
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Retrofit
|
||||
import ru.fincode.tsudesk.core.network.interceptor.DebugInterceptor
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Singleton
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import ru.fincode.tsudesk.core.network.interceptor.DebugInterceptor
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object NetworkModule {
|
||||
object OkHttpModule {
|
||||
|
||||
private const val TIMEOUT = 30L
|
||||
val logging = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOkHttpClient(): OkHttpClient =
|
||||
OkHttpClient.Builder()
|
||||
fun provideOkHttpClient(
|
||||
): OkHttpClient {
|
||||
return OkHttpClient.Builder()
|
||||
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
|
||||
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
|
||||
.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
|
||||
.retryOnConnectionFailure(true)
|
||||
.addInterceptor(DebugInterceptor())
|
||||
.build()
|
||||
|
||||
@Provides
|
||||
fun provideRetrofit(
|
||||
provider: RetrofitProvider,
|
||||
client: OkHttpClient
|
||||
): Retrofit = provider.process(NetworkConstants.BASE_URL, client)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package ru.fincode.tsudesk.core.network.di
|
||||
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Retrofit
|
||||
import ru.fincode.tsudesk.core.network.Constants
|
||||
import ru.fincode.tsudesk.core.network.RetrofitProvider
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object RetrofitModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRetrofit(
|
||||
provider: RetrofitProvider,
|
||||
client: OkHttpClient
|
||||
): Retrofit =
|
||||
provider.process(Constants.BASE_URL, client)
|
||||
}
|
||||
@@ -1,8 +1,17 @@
|
||||
package ru.fincode.tsudesk.core.network.model
|
||||
|
||||
sealed class NetworkError {
|
||||
object NoInternet : NetworkError()
|
||||
object Timeout : NetworkError()
|
||||
data class Http(val code: Int) : NetworkError()
|
||||
data class Unknown(val throwable: Throwable) : NetworkError()
|
||||
}
|
||||
sealed class NetworkError(open val meta: NetworkMeta) {
|
||||
|
||||
data class NoInternet(override val meta: NetworkMeta) : NetworkError(meta)
|
||||
data class Timeout(override val meta: NetworkMeta) : NetworkError(meta)
|
||||
|
||||
data class Http(
|
||||
val code: Int,
|
||||
override val meta: NetworkMeta
|
||||
) : NetworkError(meta)
|
||||
|
||||
data class Unknown(
|
||||
val throwable: Throwable,
|
||||
override val meta: NetworkMeta
|
||||
) : NetworkError(meta)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package ru.fincode.tsudesk.core.network.model
|
||||
|
||||
data class NetworkMeta(
|
||||
val startedAtMillis: Long,
|
||||
val finishedAtMillis: Long,
|
||||
val sentAtMillis: Long? = null,
|
||||
val receivedAtMillis: Long? = null
|
||||
)
|
||||
@@ -1,6 +1,6 @@
|
||||
package ru.fincode.tsudesk.core.network.model
|
||||
|
||||
sealed class NetworkResult<out T> {
|
||||
data class Success<T>(val data: T) : NetworkResult<T>()
|
||||
data class Success<T>(val data: T, val meta: NetworkMeta) : NetworkResult<T>()
|
||||
data class Error(val error: NetworkError) : NetworkResult<Nothing>()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
package ru.fincode.tsudesk.core.network.model
|
||||
|
||||
inline fun <T, R> NetworkResult<T>.map(
|
||||
transform: (T) -> R
|
||||
): NetworkResult<R> = when (this) {
|
||||
is NetworkResult.Success -> NetworkResult.Success(transform(data))
|
||||
is NetworkResult.Error -> this
|
||||
}
|
||||
transform: (T, NetworkMeta) -> R
|
||||
): NetworkResult<R> =
|
||||
when (val source = this) {
|
||||
|
||||
is NetworkResult.Success -> NetworkResult.Success(
|
||||
data = transform(source.data, source.meta),
|
||||
meta = source.meta
|
||||
)
|
||||
|
||||
is NetworkResult.Error -> NetworkResult.Error(source.error)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user