Commit 46cef878 by Aleksandr

fixed sending render files

parent 5d8ae7c7
package com.isidroid.c23.domain.use_case package com.isidroid.c23.domain.use_case
import android.content.Context import android.content.Context
import com.isidroid.c23.data.source.local.AppDataBase
import com.isidroid.job_sender.SendJobWorker import com.isidroid.job_sender.SendJobWorker
import com.isidroid.c23.ext.isDebug import com.isidroid.c23.ext.isDebug
import com.isidroid.c23.ui.screen.home.HomeContract import com.isidroid.c23.ui.screen.home.HomeContract
import com.isidroid.core.DiMock
import com.isidroid.core.FlowResult import com.isidroid.core.FlowResult
import com.isidroid.session.repository.SessionRepository import com.isidroid.session.repository.SessionRepository
import com.isidroid.spot.repository.ActiveSpotRepository import com.isidroid.spot.repository.ActiveSpotRepository
...@@ -17,11 +19,17 @@ import javax.inject.Singleton ...@@ -17,11 +19,17 @@ import javax.inject.Singleton
class HomeUseCase @Inject constructor( class HomeUseCase @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context,
private val sessionRepository: SessionRepository, private val sessionRepository: SessionRepository,
private val activeSpotRepository: ActiveSpotRepository private val activeSpotRepository: ActiveSpotRepository,
private val appDataBase: AppDataBase
) { ) {
fun createSession() = flow { fun createSession() = flow {
emit(FlowResult.Loading) emit(FlowResult.Loading)
// if (isDebug()) {
// appDataBase.clearAllTables()
// }
SendJobWorker.create(context) SendJobWorker.create(context)
val maxDelay = if (isDebug()) 0 else 3_000 val maxDelay = if (isDebug()) 0 else 3_000
...@@ -35,13 +43,15 @@ class HomeUseCase @Inject constructor( ...@@ -35,13 +43,15 @@ class HomeUseCase @Inject constructor(
val navigation = when { val navigation = when {
!hasSession -> HomeContract.Effect.Navigation.ToLogin !hasSession -> HomeContract.Effect.Navigation.ToLogin
!hasDefaultSpot -> HomeContract.Effect.Navigation.ToSelectSpot( !hasDefaultSpot -> HomeContract.Effect.Navigation.ToSelectSpot(
// lat = 37.2451678, lat = 38.8870757,
// lng = -121.9752617 lng = -94.6933749
lat = 37.2451678,
lng = -121.9752617, // lat = 37.2451678,
// lng = -121.9752617,
) )
else -> HomeContract.Effect.Navigation.ToSelectContent else -> HomeContract.Effect.Navigation.ToSelectContent
} }
......
...@@ -3,7 +3,7 @@ package com.isidroid.c23.domain.use_case ...@@ -3,7 +3,7 @@ package com.isidroid.c23.domain.use_case
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import com.isidroid.c23.domain.dto.PrintJobListItem import com.isidroid.c23.domain.dto.PrintJobListItem
import com.isidroid.core.FlowResult import com.isidroid.core.FlowResult
import com.isidroid.job.constant.statusName import com.isidroid.job.constant.jobStatusName
import com.isidroid.job.repository.JobRepository import com.isidroid.job.repository.JobRepository
import com.isidroid.rendering.constant.printSizeName import com.isidroid.rendering.constant.printSizeName
import com.isidroid.spot.repository.SpotRepository import com.isidroid.spot.repository.SpotRepository
...@@ -36,7 +36,7 @@ class PrintJobsUseCase @Inject constructor( ...@@ -36,7 +36,7 @@ class PrintJobsUseCase @Inject constructor(
comment = job.comment, comment = job.comment,
copies = job.copies, copies = job.copies,
cover = job.sourceFiles?.firstOrNull()?.takeIf { File(it).exists() }, cover = job.sourceFiles?.firstOrNull()?.takeIf { File(it).exists() },
statusName = job.status.statusName.lowercase(), statusName = job.status.jobStatusName.lowercase(),
accessCode = job.accessCode.orEmpty(), accessCode = job.accessCode.orEmpty(),
createdAt = job.createdAt createdAt = job.createdAt
) )
......
...@@ -35,11 +35,8 @@ class RenderUseCase @Inject constructor( ...@@ -35,11 +35,8 @@ class RenderUseCase @Inject constructor(
fun loadSpot() = flow { fun loadSpot() = flow {
val richSpot = spotRepository.getDefaultSpot() val richSpot = spotRepository.getDefaultSpot()
if (richSpot?.printProfiles.isNullOrEmpty()) throw SpotHasNoPrintProfilesException( if (richSpot?.printProfiles.isNullOrEmpty())
context.getString( throw SpotHasNoPrintProfilesException(context.getString(R.string.error_spot_has_no_printing_profiles))
R.string.error_spot_has_no_printing_profiles
)
)
emit(richSpot!!) emit(richSpot!!)
} }
......
...@@ -23,7 +23,7 @@ annotation class JobStatus { ...@@ -23,7 +23,7 @@ annotation class JobStatus {
} }
@JobStatus @JobStatus
val Int.statusName val Int.jobStatusName
get() = when (this) { get() = when (this) {
JobStatus.CREATED -> "CREATED" JobStatus.CREATED -> "CREATED"
JobStatus.CANCELED -> "CANCELED" JobStatus.CANCELED -> "CANCELED"
......
...@@ -5,5 +5,15 @@ annotation class SendJobStatus { ...@@ -5,5 +5,15 @@ annotation class SendJobStatus {
companion object { companion object {
const val RENDERED = 0 const val RENDERED = 0
const val SENDING = 1 const val SENDING = 1
const val COMPLETE = 2
} }
} }
@JobStatus
val Int.sendJobStatusName
get() = when (this) {
SendJobStatus.RENDERED -> "RENDERED"
SendJobStatus.SENDING -> "SENDING"
SendJobStatus.COMPLETE -> "COMPLETE"
else -> "Unknown"
}
\ No newline at end of file
...@@ -49,8 +49,6 @@ class SendJobWorker @AssistedInject constructor( ...@@ -49,8 +49,6 @@ class SendJobWorker @AssistedInject constructor(
var result: Result? var result: Result?
var notification: Notification? var notification: Notification?
Timber.i("==> 1")
try { try {
useCase.start() useCase.start()
notification = createNotification("Upload successfully completed") notification = createNotification("Upload successfully completed")
......
...@@ -11,8 +11,8 @@ interface SendJobDao { ...@@ -11,8 +11,8 @@ interface SendJobDao {
@Query("SELECT * FROM PrintJobSender WHERE id = :id AND printJobId = :printJobId") @Query("SELECT * FROM PrintJobSender WHERE id = :id AND printJobId = :printJobId")
fun find(id: String, printJobId: String): PrintJobSender? fun find(id: String, printJobId: String): PrintJobSender?
@Query("SELECT * FROM PrintJobSender WHERE status = :status") @Query("SELECT * FROM PrintJobSender WHERE (:status IS NULL OR status = :status)")
fun findByStatus(status: Int): List<PrintJobSender> fun findByStatus(status: Int?): List<PrintJobSender>
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg item: PrintJobSender) fun insert(vararg item: PrintJobSender)
......
...@@ -5,7 +5,7 @@ import com.isidroid.job_sender.domain.model.PrintJobSender ...@@ -5,7 +5,7 @@ import com.isidroid.job_sender.domain.model.PrintJobSender
class SendJobLocalSource(private val dao: SendJobDao) : SendJobDao { class SendJobLocalSource(private val dao: SendJobDao) : SendJobDao {
override fun find(id: String, printJobId: String): PrintJobSender? = dao.find(id, printJobId) override fun find(id: String, printJobId: String): PrintJobSender? = dao.find(id, printJobId)
override fun findByStatus(status: Int) = dao.findByStatus(status) override fun findByStatus(status: Int?) = dao.findByStatus(status)
override fun insert(vararg item: PrintJobSender) = dao.insert(*item) override fun insert(vararg item: PrintJobSender) = dao.insert(*item)
fun updateStatus(item: PrintJobSender, @SendJobStatus status: Int) = item.copy(status = status).also { insert(it) } fun updateStatus(item: PrintJobSender, @SendJobStatus status: Int) = item.copy(status = status).also { insert(it) }
......
package com.isidroid.job_sender.data.source.remote package com.isidroid.job_sender.data.source.remote
import com.isidroid.core.DiMock
import com.isidroid.job_sender.data.source.remote.api.ApiCommand import com.isidroid.job_sender.data.source.remote.api.ApiCommand
import com.isidroid.job_sender.data.source.remote.api.ApiUpload import com.isidroid.job_sender.data.source.remote.api.ApiUpload
import com.isidroid.network.ProgressEmittingRequestBody import com.isidroid.network.ProgressEmittingRequestBody
import kotlinx.coroutines.delay
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody import okhttp3.MultipartBody
...@@ -15,17 +17,27 @@ import javax.inject.Singleton ...@@ -15,17 +17,27 @@ import javax.inject.Singleton
@Singleton @Singleton
class SendJobNetworkSource @Inject constructor( class SendJobNetworkSource @Inject constructor(
private val apiUpload: ApiUpload, private val apiUpload: ApiUpload,
private val apiCommand: ApiCommand private val apiCommand: ApiCommand,
private val isMock: Boolean
) { ) {
fun uploadPage(jobId: String, token: String, filePath: String): Boolean { suspend fun uploadPage(jobId: String, token: String, filePath: String): Boolean {
// if (isMock) {
// delay(5)
// return true
// }
val file = File(filePath) val file = File(filePath)
val requestBody = file.asRequestBody("application/octet-stream".toMediaType()) val requestBody = file.asRequestBody("application/octet-stream".toMediaType())
val response = apiUpload.upload(jobId = jobId, token = token, requestBody).execute() val response = apiUpload.upload(jobId = jobId, token = token, requestBody).execute()
return response.isSuccessful return response.isSuccessful
} }
fun complete(jobId: String, token: String): Boolean { suspend fun complete(jobId: String, token: String): Boolean {
// if (isMock) {
// delay(5)
// return true
// }
apiCommand.complete(jobId = jobId, token = token).execute() apiCommand.complete(jobId = jobId, token = token).execute()
return true return true
} }
......
...@@ -2,14 +2,19 @@ package com.isidroid.job_sender.data.source.remote.api ...@@ -2,14 +2,19 @@ package com.isidroid.job_sender.data.source.remote.api
import okhttp3.ResponseBody import okhttp3.ResponseBody
import retrofit2.Call import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.Header import retrofit2.http.Header
import retrofit2.http.PATCH import retrofit2.http.PATCH
import retrofit2.http.Path import retrofit2.http.Path
interface ApiCommand { interface ApiCommand {
@FormUrlEncoded
@PATCH("api/job/{jobId}") @PATCH("api/job/{jobId}")
fun complete( fun complete(
@Path("jobId") jobId: String, @Path("jobId") jobId: String,
@Header("X-Access-Token") token: String, @Header("X-Access-Token") token: String,
@Field("status") status: String = "Ready"
): Call<ResponseBody> ): Call<ResponseBody>
} }
\ No newline at end of file
...@@ -37,7 +37,7 @@ object JobSenderModule { ...@@ -37,7 +37,7 @@ object JobSenderModule {
fun provideSendJobLocalSource(dao: SendJobDao) = SendJobLocalSource(dao) fun provideSendJobLocalSource(dao: SendJobDao) = SendJobLocalSource(dao)
@Provides @Singleton @Provides @Singleton
fun provideSendJobNetworkSource(apiUpload: ApiUpload, apiCommand: ApiCommand) = SendJobNetworkSource(apiUpload, apiCommand) fun provideSendJobNetworkSource(apiUpload: ApiUpload, apiCommand: ApiCommand, @DiMock isMock: Boolean) = SendJobNetworkSource(apiUpload, apiCommand, isMock)
@Provides @Singleton @Provides @Singleton
fun provideJobSendRepository( fun provideJobSendRepository(
...@@ -83,7 +83,7 @@ object JobSenderModule { ...@@ -83,7 +83,7 @@ object JobSenderModule {
) = createRetrofitApiClient( ) = createRetrofitApiClient(
baseUrl = serverUrl, baseUrl = serverUrl,
cl = ApiUpload::class.java, cl = ApiUpload::class.java,
logLevel = HttpLoggingInterceptor.Level.HEADERS, logLevel = HttpLoggingInterceptor.Level.BODY,
gson = gson, gson = gson,
isDebugBuild = isDebugBuild, isDebugBuild = isDebugBuild,
interceptors = listOf(authInterceptor, mockInterceptor, cacheInterceptor) interceptors = listOf(authInterceptor, mockInterceptor, cacheInterceptor)
......
...@@ -3,7 +3,10 @@ package com.isidroid.job_sender.domain.use_case ...@@ -3,7 +3,10 @@ package com.isidroid.job_sender.domain.use_case
import com.isidroid.core.DiMock import com.isidroid.core.DiMock
import com.isidroid.job.constant.JobStatus import com.isidroid.job.constant.JobStatus
import com.isidroid.job.constant.SendJobStatus import com.isidroid.job.constant.SendJobStatus
import com.isidroid.job.constant.jobStatusName
import com.isidroid.job.constant.sendJobStatusName
import com.isidroid.job_sender.repository.JobSendRepository import com.isidroid.job_sender.repository.JobSendRepository
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
...@@ -16,5 +19,12 @@ class SendPrintJobsUseCase @Inject constructor( ...@@ -16,5 +19,12 @@ class SendPrintJobsUseCase @Inject constructor(
repository.checkNotRenderedPrintJobs(repository.getJobList(JobStatus.IDLE)) repository.checkNotRenderedPrintJobs(repository.getJobList(JobStatus.IDLE))
repository.readFilesAndSend(repository.getJobSenderList(SendJobStatus.RENDERED)) repository.readFilesAndSend(repository.getJobSenderList(SendJobStatus.RENDERED))
repository.markJobUploaded(repository.getJobList(JobStatus.RENDER_UPLOAD)) repository.markJobUploaded(repository.getJobList(JobStatus.RENDER_UPLOAD))
// let's check
val printJobs = repository.getJobList(status = null)
val pages = repository.getJobSenderList(status = null)
Timber.i("===> printJobs: count=${printJobs.size}, list=${printJobs.map { it.status.jobStatusName }}")
Timber.i("===> pages: count=${pages.size}, list=${pages.map { it.status.sendJobStatusName }}")
} }
} }
\ No newline at end of file
...@@ -6,8 +6,8 @@ import com.isidroid.job_sender.domain.model.PrintJobSender ...@@ -6,8 +6,8 @@ import com.isidroid.job_sender.domain.model.PrintJobSender
interface JobSendRepository { interface JobSendRepository {
suspend fun completeUpload(jobId: String, token: String): PrintJob? suspend fun completeUpload(jobId: String, token: String): PrintJob?
suspend fun getJobList(status: Int): Collection<PrintJob> suspend fun getJobList(status: Int?): Collection<PrintJob>
suspend fun getJobSenderList(status: Int): Collection<PrintJobSender> suspend fun getJobSenderList(status: Int?): Collection<PrintJobSender>
suspend fun checkNotRenderedPrintJobs(items: Collection<PrintJob>): Collection<PrintJobSender>? suspend fun checkNotRenderedPrintJobs(items: Collection<PrintJob>): Collection<PrintJobSender>?
suspend fun readFilesAndSend(items: Collection<PrintJobSender>): Collection<PrintJob> suspend fun readFilesAndSend(items: Collection<PrintJobSender>): Collection<PrintJob>
suspend fun markJobUploaded(items: Collection<PrintJob>): Collection<PrintJob> suspend fun markJobUploaded(items: Collection<PrintJob>): Collection<PrintJob>
......
package com.isidroid.job_sender.repository package com.isidroid.job_sender.repository
import com.isidroid.job.constant.JobStatus import com.isidroid.job.constant.JobStatus
import com.isidroid.job.constant.SendJobStatus
import com.isidroid.job.constant.jobStatusName
import com.isidroid.job.model.PrintJob import com.isidroid.job.model.PrintJob
import com.isidroid.job.repository.JobRepository import com.isidroid.job.repository.JobRepository
import com.isidroid.job_sender.SendJobEventCollectorFlow import com.isidroid.job_sender.SendJobEventCollectorFlow
...@@ -12,7 +14,6 @@ import com.isidroid.job_sender.ext.createRenderItems ...@@ -12,7 +14,6 @@ import com.isidroid.job_sender.ext.createRenderItems
import com.isidroid.job_sender.ext.decreaseCounter import com.isidroid.job_sender.ext.decreaseCounter
import com.isidroid.rendering.repository.RenderRepository import com.isidroid.rendering.repository.RenderRepository
import com.isidroid.spot.repository.SpotRepository import com.isidroid.spot.repository.SpotRepository
import kotlinx.coroutines.delay
import timber.log.Timber import timber.log.Timber
internal class JobSendRepositoryImpl( internal class JobSendRepositoryImpl(
...@@ -32,8 +33,8 @@ internal class JobSendRepositoryImpl( ...@@ -32,8 +33,8 @@ internal class JobSendRepositoryImpl(
return printJob?.copy(status = JobStatus.READY_TO_PRINT)?.also { printJobRepository.insert(it) }?.takeIf { uploadResult } return printJob?.copy(status = JobStatus.READY_TO_PRINT)?.also { printJobRepository.insert(it) }?.takeIf { uploadResult }
} }
override suspend fun getJobList(status: Int): Collection<PrintJob> = printJobRepository.readLocalList(status = status) override suspend fun getJobList(status: Int?): Collection<PrintJob> = printJobRepository.readLocalList(status = status)
override suspend fun getJobSenderList(status: Int): Collection<PrintJobSender> = sendJobLocalSource.findByStatus(status) override suspend fun getJobSenderList(status: Int?): Collection<PrintJobSender> = sendJobLocalSource.findByStatus(status)
// let's check whether there is not rendered print jobs // let's check whether there is not rendered print jobs
override suspend fun checkNotRenderedPrintJobs(items: Collection<PrintJob>): Collection<PrintJobSender>? { override suspend fun checkNotRenderedPrintJobs(items: Collection<PrintJob>): Collection<PrintJobSender>? {
...@@ -58,27 +59,37 @@ internal class JobSendRepositoryImpl( ...@@ -58,27 +59,37 @@ internal class JobSendRepositoryImpl(
for ((index, item) in items.withIndex()) { for ((index, item) in items.withIndex()) {
eventCollector.updateProgress(index, total) eventCollector.updateProgress(index, total)
try { try {
sendJobLocalSource.updateStatus(item, SendJobStatus.SENDING)
val uploadResult = sendJobNetworkSource.uploadPage(jobId = item.printJobId, token = item.accessToken, filePath = item.sourceFile) val uploadResult = sendJobNetworkSource.uploadPage(jobId = item.printJobId, token = item.accessToken, filePath = item.sourceFile)
if (!uploadResult) if (!uploadResult)
throw UploadPageException() throw UploadPageException()
sendJobResults.decreaseCounter(item.printJobId) sendJobResults.decreaseCounter(item.printJobId)
sendJobLocalSource.updateStatus(item, SendJobStatus.COMPLETE)
} catch (t: Throwable) { } catch (t: Throwable) {
sendJobLocalSource.updateStatus(item, SendJobStatus.RENDERED)
Timber.e(t) Timber.e(t)
eventCollector.jobError(jobId = item.printJobId, t = t) eventCollector.jobError(jobId = item.printJobId, t = t)
} }
} }
Timber.i("===> readFilesAndSend sendJobResults=${sendJobResults}")
eventCollector.updateProgress(total, total) eventCollector.updateProgress(total, total)
// update jobs // update jobs
val successJobIds = sendJobResults.filter { it.value == 0 }.keys val successJobIds = sendJobResults.filter { it.value == 0 }.keys
printJobRepository.updateJobStatus(status = JobStatus.RENDER_UPLOAD, *successJobIds.toTypedArray()) printJobRepository.updateJobStatus(status = JobStatus.RENDER_UPLOAD, *successJobIds.toTypedArray())
Timber.i("===> readFilesAndSend successJobIds=$successJobIds")
val failedJobIds = sendJobResults.filter { it.value != 0 }.keys val failedJobIds = sendJobResults.filter { it.value != 0 }.keys
printJobRepository.updateJobStatus(status = JobStatus.UPLOAD_ERROR, *failedJobIds.toTypedArray()) printJobRepository.updateJobStatus(status = JobStatus.UPLOAD_ERROR, *failedJobIds.toTypedArray())
Timber.i("===> readFilesAndSend failedJobIds=$failedJobIds")
val successJobs = printJobRepository.readLocalList(ids = successJobIds.toList()) val successJobs = printJobRepository.readLocalList(ids = successJobIds.toList())
val failedJobs = printJobRepository.readLocalList(ids = failedJobIds.toList()) val failedJobs = printJobRepository.readLocalList(ids = failedJobIds.toList())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment