mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-15 15:02:49 +01:00
refactor(GoogleDrive): Use gson to encode the syncData.
So on a really big data we will run into OOM issue. With this change we implement streaming approach, rather than loading the entire JSON string into memory at once. Signed-off-by: KaiserBh <kaiserbh@proton.me>
This commit is contained in:
parent
97cf79f948
commit
b23c100fab
@ -19,6 +19,8 @@ import com.google.api.services.drive.Drive
|
|||||||
import com.google.api.services.drive.DriveScopes
|
import com.google.api.services.drive.DriveScopes
|
||||||
import com.google.api.services.drive.model.File
|
import com.google.api.services.drive.model.File
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -128,17 +130,21 @@ class GoogleDriveSyncService(context: Context, json: Json, syncPreferences: Sync
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun pushSyncData(syncData: SyncData) {
|
override suspend fun pushSyncData(syncData: SyncData) {
|
||||||
val jsonData = json.encodeToString(syncData)
|
|
||||||
val drive = googleDriveService.driveService
|
val drive = googleDriveService.driveService
|
||||||
?: throw Exception(context.getString(R.string.google_drive_not_signed_in))
|
?: throw Exception(context.stringResource(MR.strings.google_drive_not_signed_in))
|
||||||
|
|
||||||
val fileList = getFileList(drive)
|
val fileList = getFileList(drive)
|
||||||
|
|
||||||
val byteArrayOutputStream = ByteArrayOutputStream()
|
val byteArrayOutputStream = ByteArrayOutputStream()
|
||||||
|
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val gzipOutputStream = GZIPOutputStream(byteArrayOutputStream)
|
val gzipOutputStream = GZIPOutputStream(byteArrayOutputStream)
|
||||||
gzipOutputStream.write(jsonData.toByteArray(Charsets.UTF_8))
|
val jsonWriter = JsonWriter(OutputStreamWriter(gzipOutputStream, Charsets.UTF_8))
|
||||||
gzipOutputStream.close()
|
val gson = Gson()
|
||||||
|
|
||||||
|
jsonWriter.use { jWriter ->
|
||||||
|
gson.toJson(syncData, SyncData::class.java, jWriter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val byteArrayContent = ByteArrayContent("application/octet-stream", byteArrayOutputStream.toByteArray())
|
val byteArrayContent = ByteArrayContent("application/octet-stream", byteArrayOutputStream.toByteArray())
|
||||||
@ -154,6 +160,7 @@ class GoogleDriveSyncService(context: Context, json: Json, syncPreferences: Sync
|
|||||||
val fileMetadata = File().apply {
|
val fileMetadata = File().apply {
|
||||||
name = remoteFileName
|
name = remoteFileName
|
||||||
mimeType = "application/gzip"
|
mimeType = "application/gzip"
|
||||||
|
parents = listOf("appDataFolder")
|
||||||
}
|
}
|
||||||
val uploadedFile = drive.files().create(fileMetadata, byteArrayContent)
|
val uploadedFile = drive.files().create(fileMetadata, byteArrayContent)
|
||||||
.setFields("id")
|
.setFields("id")
|
||||||
@ -168,19 +175,20 @@ class GoogleDriveSyncService(context: Context, json: Json, syncPreferences: Sync
|
|||||||
deleteLockFile(drive)
|
deleteLockFile(drive)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logcat(LogPriority.ERROR) { "Failed to push or update sync data: ${e.message}" }
|
logcat(LogPriority.ERROR) { "Failed to push or update sync data: ${e.message}" }
|
||||||
|
throw Exception(context.stringResource(MR.strings.error_uploading_sync_data) + ": ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFileList(drive: Drive): MutableList<File> {
|
private fun getAppDataFileList(drive: Drive): MutableList<File> {
|
||||||
try {
|
try {
|
||||||
// Search for the existing file by name
|
// Search for the existing file by name in the appData folder
|
||||||
val query = "mimeType='application/gzip' and trashed = false and name = '$remoteFileName'"
|
val query = "mimeType='application/gzip' and name = '$remoteFileName'"
|
||||||
val fileList = drive.files().list().setQ(query).execute().files
|
val fileList = drive.files().list().setSpaces("appDataFolder").setQ(query).setFields("files(id, name, createdTime)").execute().files
|
||||||
Log.d("GoogleDrive", "File list: $fileList")
|
Log.d("GoogleDrive", "AppData folder file list: $fileList")
|
||||||
|
|
||||||
return fileList
|
return fileList
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("GoogleDrive", "Error no sync data found: ${e.message}")
|
Log.e("GoogleDrive", "Error no sync data found in appData folder: ${e.message}")
|
||||||
return mutableListOf()
|
return mutableListOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,7 +326,7 @@ class GoogleDriveService(private val context: Context) {
|
|||||||
NetHttpTransport(),
|
NetHttpTransport(),
|
||||||
jsonFactory,
|
jsonFactory,
|
||||||
secrets,
|
secrets,
|
||||||
listOf(DriveScopes.DRIVE_FILE),
|
listOf(DriveScopes.DRIVE_FILE, DriveScopes.DRIVE_APPDATA),
|
||||||
).setAccessType("offline").build()
|
).setAccessType("offline").build()
|
||||||
|
|
||||||
return flow.newAuthorizationUrl()
|
return flow.newAuthorizationUrl()
|
||||||
|
Loading…
Reference in New Issue
Block a user