Refact network model (#123)

* refact: [NETWORK] model with error

* refact: [NETWORK] model with error

* refact: [NETWORK] model with error

* refact: [NETWORK] model with error

* refact: [NETWORK] model with error

* refact

* merged with main

---------

Co-authored-by: Florent Champigny <florent@bere.al>
This commit is contained in:
Florent CHAMPIGNY 2025-08-21 10:25:03 +02:00 committed by GitHub
parent db3c8a118c
commit 35d896af23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 571 additions and 504 deletions

View file

@ -38,12 +38,12 @@ class ImagesRepositoryImpl(
deviceId: String,
call: FloconNetworkCallDomainModel,
) {
val duration = call.networkResponse?.durationMs ?: return
val duration = call.response?.durationMs ?: return
imagesLocalDataSource.addImage(
deviceId = deviceId,
image = DeviceImageDomainModel(
url = call.networkRequest.url,
time = (call.networkRequest.startTime + duration).toLong(),
url = call.request.url,
time = (call.request.startTime + duration).toLong(),
),
)
}

View file

@ -5,7 +5,6 @@ import io.github.openflocon.domain.messages.models.FloconIncomingMessageDomainMo
import io.github.openflocon.domain.network.models.BadQualityConfigDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkCallDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkCallIdDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkResponseDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkResponseOnlyDomainModel
import io.github.openflocon.domain.network.models.MockNetworkDomainModel

View file

@ -14,6 +14,7 @@ import io.github.openflocon.domain.network.models.BadQualityConfigId
import io.github.openflocon.domain.network.models.FloconNetworkCallDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkResponseOnlyDomainModel
import io.github.openflocon.domain.network.models.MockNetworkDomainModel
import io.github.openflocon.domain.network.models.getContentType
import io.github.openflocon.domain.network.repository.NetworkBadQualityRepository
import io.github.openflocon.domain.network.repository.NetworkImageRepository
import io.github.openflocon.domain.network.repository.NetworkMocksRepository
@ -100,7 +101,7 @@ class NetworkRepositoryImpl(
}
toDomainForResponse(response = response, request = request)
}?.let { call ->
if (call.networkResponse?.contentType?.startsWith("image/") == true) {
if (call.response?.getContentType()?.startsWith("image/") == true) {
networkImageRepository.onImageReceived(deviceId = deviceId, call = call)
}
networkLocalDataSource.save(
@ -159,48 +160,31 @@ class NetworkRepositoryImpl(
response: FloconNetworkResponseOnlyDomainModel,
request: FloconNetworkCallDomainModel,
): FloconNetworkCallDomainModel? {
try {
val networkResponse = response.networkResponse
return when (request) {
is FloconNetworkCallDomainModel.GraphQl -> {
// throw an exception if not http
val responseHttp = response as FloconNetworkResponseOnlyDomainModel.Http
val response = FloconNetworkCallDomainModel.GraphQl.Response(
networkResponse = networkResponse,
httpCode = responseHttp.httpCode,
isSuccess = responseHttp.httpCode in 200..299,
)
request.copy(
response = response,
)
return try {
val response = when (val r = response.response) {
is FloconNetworkCallDomainModel.Response.Success -> {
// specific case : map to graphQl if needed
when (val s = r.specificInfos) {
is FloconNetworkCallDomainModel.Response.Success.SpecificInfos.Http -> {
r.copy(
specificInfos = FloconNetworkCallDomainModel.Response.Success.SpecificInfos.GraphQl(
httpCode = s.httpCode,
isSuccess = s.httpCode in 200..299
)
)
}
else -> r
}
}
is FloconNetworkCallDomainModel.Grpc -> {
val responseHttp = response as FloconNetworkResponseOnlyDomainModel.Grpc
val response = FloconNetworkCallDomainModel.Grpc.Response(
networkResponse = networkResponse,
responseStatus = responseHttp.grpcStatus,
)
request.copy(
response = response,
)
}
is FloconNetworkCallDomainModel.Http -> {
val responseHttp = response as FloconNetworkResponseOnlyDomainModel.Http
val response = FloconNetworkCallDomainModel.Http.Response(
networkResponse = networkResponse,
httpCode = responseHttp.httpCode,
)
request.copy(
response = response,
)
}
is FloconNetworkCallDomainModel.Response.Failure -> response.response
}
request.copy(
response = response,
)
} catch (t: Throwable) {
t.printStackTrace()
return null
null
}
}

View file

@ -2,81 +2,68 @@ package io.github.openflocon.data.local.network.mapper
import io.github.openflocon.data.local.network.models.FloconNetwockCallEntityLite
import io.github.openflocon.data.local.network.models.FloconNetworkCallType
import io.github.openflocon.data.local.network.models.FloconNetworkRequestLiteEmbedded
import io.github.openflocon.data.local.network.models.FloconNetworkResponseLiteEmbedded
import io.github.openflocon.domain.network.models.FloconNetworkCallDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkRequestDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkResponseDomainModel
import kotlin.Boolean
fun toDomainModel(request: FloconNetworkRequestLiteEmbedded): FloconNetworkRequestDomainModel {
return with(request) {
FloconNetworkRequestDomainModel(
url = this.url,
method = this.method,
startTime = this.startTime,
headers = this.requestHeaders,
body = null, // null on lite
byteSize = this.requestByteSize,
isMocked = this.isMocked,
)
}
}
fun FloconNetwockCallEntityLite.toDomainModel(): FloconNetworkCallDomainModel? {
return try {
val networkRequest = toDomainModel(request)
when (type) {
FloconNetworkCallType.HTTP -> FloconNetworkCallDomainModel.Http(
callId = callId,
networkRequest = networkRequest,
response = response?.let {
FloconNetworkCallDomainModel.Http.Response(
httpCode = response.http!!.responseHttpCode,
networkResponse = toDomainModel(response),
)
}
)
FloconNetworkCallType.GRAPHQL -> FloconNetworkCallDomainModel.GraphQl(
callId = callId,
request = FloconNetworkCallDomainModel.GraphQl.Request(
networkRequest = networkRequest,
query = request.graphql!!.query,
operationType = request.graphql.operationType,
),
response = response?.let {
FloconNetworkCallDomainModel.GraphQl.Response(
httpCode = response.graphql!!.responseHttpCode,
isSuccess = response.graphql.isSuccess,
networkResponse = toDomainModel(response),
)
}
)
FloconNetworkCallType.GRPC -> FloconNetworkCallDomainModel.Grpc(
callId = callId,
networkRequest = networkRequest,
response = response?.let {
FloconNetworkCallDomainModel.Grpc.Response(
networkResponse = toDomainModel(response),
responseStatus = response.grpc!!.responseStatus,
)
}
)
}
FloconNetworkCallDomainModel(
callId = callId,
request = toRequestDomainModel(),
response = response?.toDomainModel(),
)
} catch (t: Throwable) {
t.printStackTrace()
return null
}
}
private fun toDomainModel(response: FloconNetworkResponseLiteEmbedded): FloconNetworkResponseDomainModel = with(response) {
FloconNetworkResponseDomainModel(
contentType = responseContentType,
private fun FloconNetwockCallEntityLite.toRequestDomainModel(): FloconNetworkCallDomainModel.Request =
FloconNetworkCallDomainModel.Request(
url = request.url,
method = request.method,
startTime = request.startTime,
headers = request.requestHeaders,
body = null, // null on lite
headers = responseHeaders,
byteSize = responseByteSize,
durationMs = durationMs,
byteSize = request.requestByteSize,
isMocked = request.isMocked,
specificInfos = when (type) {
FloconNetworkCallType.HTTP -> FloconNetworkCallDomainModel.Request.SpecificInfos.Http
FloconNetworkCallType.GRAPHQL -> FloconNetworkCallDomainModel.Request.SpecificInfos.GraphQl(
query = request.graphql!!.query,
operationType = request.graphql.operationType,
)
FloconNetworkCallType.GRPC -> FloconNetworkCallDomainModel.Request.SpecificInfos.Grpc
},
)
private fun FloconNetworkResponseLiteEmbedded.toDomainModel(): FloconNetworkCallDomainModel.Response? {
return if(responseError != null) {
FloconNetworkCallDomainModel.Response.Failure(
durationMs = durationMs,
responseError
)
} else {
FloconNetworkCallDomainModel.Response.Success(
contentType = responseContentType,
body = null, // null on lite
headers = responseHeaders,
byteSize = responseByteSize,
durationMs = durationMs,
specificInfos = when {
graphql != null -> FloconNetworkCallDomainModel.Response.Success.SpecificInfos.GraphQl(
httpCode = graphql.responseHttpCode,
isSuccess = graphql.isSuccess,
)
grpc != null -> FloconNetworkCallDomainModel.Response.Success.SpecificInfos.Grpc(
grpcStatus = grpc.responseStatus,
)
http != null -> FloconNetworkCallDomainModel.Response.Success.SpecificInfos.Http(
httpCode = http.responseHttpCode,
)
else -> return null
}
)
}
}

View file

@ -2,82 +2,70 @@ package io.github.openflocon.data.local.network.mapper
import io.github.openflocon.data.local.network.models.FloconNetworkCallEntity
import io.github.openflocon.data.local.network.models.FloconNetworkCallType
import io.github.openflocon.data.local.network.models.FloconNetworkRequestEmbedded
import io.github.openflocon.data.local.network.models.FloconNetworkResponseEmbedded
import io.github.openflocon.domain.network.models.FloconNetworkCallDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkRequestDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkResponseDomainModel
private fun toDomainModel(request: FloconNetworkRequestEmbedded): FloconNetworkRequestDomainModel {
return with(request) {
FloconNetworkRequestDomainModel(
url = this.url,
method = this.method,
startTime = this.startTime,
headers = this.requestHeaders,
body = this.requestBody,
byteSize = this.requestByteSize,
isMocked = this.isMocked,
)
}
}
fun FloconNetworkCallEntity.toDomainModel(): FloconNetworkCallDomainModel? {
return try {
val networkRequest = toDomainModel(request)
when (type) {
FloconNetworkCallType.HTTP -> FloconNetworkCallDomainModel.Http(
callId = callId,
networkRequest = networkRequest,
response = response?.let {
FloconNetworkCallDomainModel.Http.Response(
httpCode = response.http!!.responseHttpCode,
networkResponse = toDomainModel(response),
)
}
)
FloconNetworkCallType.GRAPHQL -> FloconNetworkCallDomainModel.GraphQl(
callId = callId,
request = FloconNetworkCallDomainModel.GraphQl.Request(
networkRequest = networkRequest,
query = request.graphql!!.query,
operationType = request.graphql.operationType,
),
response = response?.let {
FloconNetworkCallDomainModel.GraphQl.Response(
httpCode = response.graphql!!.responseHttpCode,
isSuccess = response.graphql.isSuccess,
networkResponse = toDomainModel(response),
)
}
)
FloconNetworkCallType.GRPC -> FloconNetworkCallDomainModel.Grpc(
callId = callId,
networkRequest = networkRequest,
response = response?.let {
FloconNetworkCallDomainModel.Grpc.Response(
networkResponse = toDomainModel(response),
responseStatus = response.grpc!!.responseStatus,
)
}
)
}
FloconNetworkCallDomainModel(
callId = callId,
request = toRequestDomainModel(),
response = response?.toDomainModel(),
)
} catch (t: Throwable) {
t.printStackTrace()
return null
}
}
private fun toDomainModel(response: FloconNetworkResponseEmbedded): FloconNetworkResponseDomainModel =
with(response) {
FloconNetworkResponseDomainModel(
private fun FloconNetworkCallEntity.toRequestDomainModel(): FloconNetworkCallDomainModel.Request =
FloconNetworkCallDomainModel.Request(
url = request.url,
method = request.method,
startTime = request.startTime,
headers = request.requestHeaders,
body = request.requestBody,
byteSize = request.requestByteSize,
isMocked = request.isMocked,
specificInfos = when (type) {
FloconNetworkCallType.HTTP -> FloconNetworkCallDomainModel.Request.SpecificInfos.Http
FloconNetworkCallType.GRAPHQL -> FloconNetworkCallDomainModel.Request.SpecificInfos.GraphQl(
query = request.graphql!!.query,
operationType = request.graphql.operationType,
)
FloconNetworkCallType.GRPC -> FloconNetworkCallDomainModel.Request.SpecificInfos.Grpc
},
)
private fun FloconNetworkResponseEmbedded.toDomainModel(): FloconNetworkCallDomainModel.Response? {
return if(responseError != null) {
FloconNetworkCallDomainModel.Response.Failure(
durationMs = durationMs,
issue = responseError
)
} else {
FloconNetworkCallDomainModel.Response.Success(
contentType = responseContentType,
body = responseBody,
headers = responseHeaders,
byteSize = responseByteSize,
durationMs = durationMs,
specificInfos = when {
graphql != null -> FloconNetworkCallDomainModel.Response.Success.SpecificInfos.GraphQl(
httpCode = graphql.responseHttpCode,
isSuccess = graphql.isSuccess,
)
grpc != null -> FloconNetworkCallDomainModel.Response.Success.SpecificInfos.Grpc(
grpcStatus = grpc.responseStatus,
)
http != null -> FloconNetworkCallDomainModel.Response.Success.SpecificInfos.Http(
httpCode = http.responseHttpCode,
)
else -> return null
}
)
}
}

View file

@ -19,61 +19,75 @@ fun FloconNetworkCallDomainModel.toEntity(
callId = callId,
deviceId = deviceId,
packageName = packageName,
type = when (this) {
is FloconNetworkCallDomainModel.Http -> FloconNetworkCallType.HTTP
is FloconNetworkCallDomainModel.GraphQl -> FloconNetworkCallType.GRAPHQL
is FloconNetworkCallDomainModel.Grpc -> FloconNetworkCallType.GRPC
type = when (this.request.specificInfos) {
is FloconNetworkCallDomainModel.Request.SpecificInfos.Http -> FloconNetworkCallType.HTTP
is FloconNetworkCallDomainModel.Request.SpecificInfos.GraphQl -> FloconNetworkCallType.GRAPHQL
is FloconNetworkCallDomainModel.Request.SpecificInfos.Grpc -> FloconNetworkCallType.GRPC
},
request = FloconNetworkRequestEmbedded(
url = networkRequest.url,
method = networkRequest.method,
startTime = networkRequest.startTime,
requestHeaders = networkRequest.headers,
requestBody = networkRequest.body,
requestByteSize = networkRequest.byteSize,
isMocked = networkRequest.isMocked,
graphql = when (this) {
is FloconNetworkCallDomainModel.GraphQl -> NetworkCallGraphQlRequestEmbedded(
query = this.request.query,
operationType = this.request.operationType,
url = request.url,
method = request.method,
startTime = request.startTime,
requestHeaders = request.headers,
requestBody = request.body,
requestByteSize = request.byteSize,
isMocked = request.isMocked,
graphql = when (val s = this.request.specificInfos) {
is FloconNetworkCallDomainModel.Request.SpecificInfos.GraphQl -> NetworkCallGraphQlRequestEmbedded(
query = s.query,
operationType = s.operationType,
)
else -> null
}
),
response = networkResponse?.let { networkResponse ->
FloconNetworkResponseEmbedded(
durationMs = networkResponse.durationMs,
responseContentType = networkResponse.contentType,
responseBody = networkResponse.body,
responseHeaders = networkResponse.headers,
responseByteSize = networkResponse.byteSize,
graphql = when (this) {
is FloconNetworkCallDomainModel.GraphQl -> NetworkCallGraphQlResponseEmbedded(
responseHttpCode = (this.response as FloconNetworkCallDomainModel.GraphQl.Response).httpCode,
isSuccess = (this.response as FloconNetworkCallDomainModel.GraphQl.Response).isSuccess,
response = response?.let { networkResponse ->
when(networkResponse) {
is FloconNetworkCallDomainModel.Response.Failure -> {
FloconNetworkResponseEmbedded(
durationMs = networkResponse.durationMs,
responseError = networkResponse.issue,
graphql = null,
http = null,
grpc = null,
responseContentType = null,
responseBody = null,
responseHeaders = emptyMap(),
responseByteSize = 0,
)
is FloconNetworkCallDomainModel.Grpc,
is FloconNetworkCallDomainModel.Http -> null
},
http = when (this) {
is FloconNetworkCallDomainModel.Http -> NetworkCallHttpResponseEmbedded(
responseHttpCode = (this.response as FloconNetworkCallDomainModel.Http.Response).httpCode,
)
is FloconNetworkCallDomainModel.Grpc,
is FloconNetworkCallDomainModel.GraphQl -> null
},
grpc = when (this) {
is FloconNetworkCallDomainModel.Grpc -> NetworkCallGrpcResponseEmbedded(
responseStatus = (this.response as FloconNetworkCallDomainModel.Grpc.Response).responseStatus,
)
is FloconNetworkCallDomainModel.Http,
is FloconNetworkCallDomainModel.GraphQl -> null
}
)
is FloconNetworkCallDomainModel.Response.Success -> {
FloconNetworkResponseEmbedded(
durationMs = networkResponse.durationMs,
responseContentType = networkResponse.contentType,
responseBody = networkResponse.body,
responseHeaders = networkResponse.headers,
responseByteSize = networkResponse.byteSize,
responseError = null,
graphql = when (val s = networkResponse.specificInfos) {
is FloconNetworkCallDomainModel.Response.Success.SpecificInfos.GraphQl -> NetworkCallGraphQlResponseEmbedded(
responseHttpCode = s.httpCode,
isSuccess = s.isSuccess,
)
else -> null
},
http = when (val s = networkResponse.specificInfos) {
is FloconNetworkCallDomainModel.Response.Success.SpecificInfos.Http -> NetworkCallHttpResponseEmbedded(
responseHttpCode = s.httpCode,
)
else -> null
},
grpc = when (val s = networkResponse.specificInfos) {
is FloconNetworkCallDomainModel.Response.Success.SpecificInfos.Grpc -> NetworkCallGrpcResponseEmbedded(
responseStatus = s.grpcStatus,
)
else -> null
}
)
}
}
}
)
}

View file

@ -36,6 +36,7 @@ data class FloconNetworkRequestLiteEmbedded(
data class FloconNetworkResponseLiteEmbedded(
val durationMs: Double,
val responseError: String?,
val responseContentType: String?,
//val responseBody: String?,
val responseHeaders: Map<String, String>,

View file

@ -54,6 +54,7 @@ data class FloconNetworkResponseEmbedded(
val responseBody: String?,
val responseHeaders: Map<String, String>,
val responseByteSize: Long,
val responseError: String?,
@Embedded(prefix = "graphql_")
val graphql: NetworkCallGraphQlResponseEmbedded?,

View file

@ -4,6 +4,7 @@ import kotlinx.serialization.json.Json
internal inline fun <reified T> Json.safeDecodeFromString(data: String): T? = try {
decodeFromString(data)
} catch (e: Throwable) {
} catch (t: Throwable) {
t.printStackTrace()
null
}

View file

@ -8,7 +8,6 @@ import io.github.openflocon.data.core.network.graphql.model.GraphQlRequestBody
import io.github.openflocon.data.core.network.graphql.model.GraphQlResponseBody
import io.github.openflocon.domain.network.models.BadQualityConfigDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkCallDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkRequestDomainModel
import io.github.openflocon.domain.network.models.MockNetworkDomainModel
import kotlinx.serialization.json.Json
import kotlin.uuid.ExperimentalUuidApi
@ -34,7 +33,8 @@ fun toDomain(decoded: FloconNetworkRequestDataModel): FloconNetworkCallDomainMod
val graphQl = extractGraphQl(decoded)
val callId = decoded.floconCallId!!
val networkRequest = FloconNetworkRequestDomainModel(
val request = FloconNetworkCallDomainModel.Request(
url = decoded.url!!,
startTime = decoded.startTime!!,
method = decoded.method!!,
@ -42,33 +42,21 @@ fun toDomain(decoded: FloconNetworkRequestDataModel): FloconNetworkCallDomainMod
body = decoded.requestBody,
byteSize = decoded.requestSize ?: 0L,
isMocked = decoded.isMocked ?: false,
specificInfos = when {
graphQl != null -> FloconNetworkCallDomainModel.Request.SpecificInfos.GraphQl(
query = graphQl.request.requestBody.query,
operationType = graphQl.request.operationType,
)
decoded.floconNetworkType == "grpc" -> FloconNetworkCallDomainModel.Request.SpecificInfos.Grpc
else -> FloconNetworkCallDomainModel.Request.SpecificInfos.Http
}
)
when {
graphQl != null -> FloconNetworkCallDomainModel.GraphQl(
callId = callId,
request = FloconNetworkCallDomainModel.GraphQl.Request(
query = graphQl.request.queryName ?: "anonymous",
operationType = graphQl.request.operationType,
networkRequest = networkRequest,
),
response = null,
)
decoded.floconNetworkType == "grpc" -> FloconNetworkCallDomainModel.Grpc(
callId = callId,
networkRequest = networkRequest,
response = null,
)
// decoded.floconNetworkType == "http"
else -> {
FloconNetworkCallDomainModel.Http(
callId = callId,
networkRequest = networkRequest,
response = null,
)
}
}
FloconNetworkCallDomainModel(
callId = callId,
request = request,
response = null, // for now it's null
)
} catch (t: Throwable) {
t.printStackTrace()
null

View file

@ -1,7 +1,7 @@
package com.flocon.data.remote.network.models
import io.github.openflocon.domain.network.models.FloconNetworkCallDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkCallIdDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkResponseDomainModel
import io.github.openflocon.domain.network.models.FloconNetworkResponseOnlyDomainModel
import kotlinx.serialization.Serializable
@ -37,31 +37,41 @@ data class FloconNetworkResponseDataModel(
val responseHeaders: Map<String, String>? = null,
val responseSize: Long? = null,
val responseGrpcStatus: String? = null,
val responseError: String? = null,
)
internal fun FloconNetworkResponseDataModel.toDomain(): FloconNetworkResponseOnlyDomainModel? {
return try {
val callId = floconCallId!!
val networkResponse = FloconNetworkResponseDomainModel(
durationMs = durationMs ?: 0.0,
body = responseBody,
byteSize = responseSize ?: 0L,
headers = responseHeaders.orEmpty(),
contentType = responseContentType,
)
when (floconNetworkType) {
"grpc" -> FloconNetworkResponseOnlyDomainModel.Grpc(
floconCallId = callId,
networkResponse = networkResponse,
grpcStatus = responseGrpcStatus!!,
val durationMs = durationMs ?: 0.0
val response = if (responseError != null) {
FloconNetworkCallDomainModel.Response.Failure(
durationMs = durationMs,
issue = responseError,
)
// otherwise tread like http
else -> FloconNetworkResponseOnlyDomainModel.Http(
floconCallId = callId,
networkResponse = networkResponse,
httpCode = responseHttpCode!!,
} else {
FloconNetworkCallDomainModel.Response.Success(
durationMs = durationMs,
contentType = responseContentType,
body = responseBody,
headers = responseHeaders.orEmpty(),
byteSize = responseSize ?: 0L,
specificInfos = when (floconNetworkType) {
"grpc" -> FloconNetworkCallDomainModel.Response.Success.SpecificInfos.Grpc(
grpcStatus = responseGrpcStatus!!,
)
// otherwise tread like http
else -> FloconNetworkCallDomainModel.Response.Success.SpecificInfos.Http(
httpCode = responseHttpCode!!,
)
}
)
}
FloconNetworkResponseOnlyDomainModel(
floconCallId = callId,
response = response,
)
} catch (t: Throwable) {
t.printStackTrace()
return null