analysis: do not chain workers, use prefs for data read/write instead
This commit is contained in:
parent
fbd498bee8
commit
a38c5b72ee
4 changed files with 23 additions and 40 deletions
|
@ -70,7 +70,7 @@ class AnalysisWorker(context: Context, parameters: WorkerParameters) : Coroutine
|
||||||
private fun onStart() {
|
private fun onStart() {
|
||||||
Log.i(LOG_TAG, "Start analysis worker $id")
|
Log.i(LOG_TAG, "Start analysis worker $id")
|
||||||
runBlocking {
|
runBlocking {
|
||||||
FlutterUtils.initFlutterEngine(applicationContext, SHARED_PREFERENCES_KEY, CALLBACK_HANDLE_KEY) {
|
FlutterUtils.initFlutterEngine(applicationContext, SHARED_PREFERENCES_KEY, PREF_CALLBACK_HANDLE_KEY) {
|
||||||
flutterEngine = it
|
flutterEngine = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,14 +78,15 @@ class AnalysisWorker(context: Context, parameters: WorkerParameters) : Coroutine
|
||||||
try {
|
try {
|
||||||
initChannels(applicationContext)
|
initChannels(applicationContext)
|
||||||
|
|
||||||
|
val preferences = applicationContext.getSharedPreferences(SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
||||||
|
val entryIdStrings = preferences.getStringSet(PREF_ENTRY_IDS_KEY, null)
|
||||||
|
|
||||||
runBlocking {
|
runBlocking {
|
||||||
FlutterUtils.runOnUiThread {
|
FlutterUtils.runOnUiThread {
|
||||||
backgroundChannel?.invokeMethod(
|
backgroundChannel?.invokeMethod(
|
||||||
"start", hashMapOf(
|
"start", hashMapOf(
|
||||||
"entryIds" to inputData.getIntArray(KEY_ENTRY_IDS)?.toList(),
|
"entryIds" to entryIdStrings?.map { Integer.parseUnsignedInt(it) }?.toList(),
|
||||||
"force" to inputData.getBoolean(KEY_FORCE, false),
|
"force" to inputData.getBoolean(KEY_FORCE, false),
|
||||||
"progressTotal" to inputData.getInt(KEY_PROGRESS_TOTAL, 0),
|
|
||||||
"progressOffset" to inputData.getInt(KEY_PROGRESS_OFFSET, 0),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -194,14 +195,12 @@ class AnalysisWorker(context: Context, parameters: WorkerParameters) : Coroutine
|
||||||
private val LOG_TAG = LogUtils.createTag<AnalysisWorker>()
|
private val LOG_TAG = LogUtils.createTag<AnalysisWorker>()
|
||||||
private const val BACKGROUND_CHANNEL = "deckers.thibault/aves/analysis_service_background"
|
private const val BACKGROUND_CHANNEL = "deckers.thibault/aves/analysis_service_background"
|
||||||
const val SHARED_PREFERENCES_KEY = "analysis_service"
|
const val SHARED_PREFERENCES_KEY = "analysis_service"
|
||||||
const val CALLBACK_HANDLE_KEY = "callback_handle"
|
const val PREF_CALLBACK_HANDLE_KEY = "callback_handle"
|
||||||
|
const val PREF_ENTRY_IDS_KEY = "entry_ids"
|
||||||
|
|
||||||
const val NOTIFICATION_CHANNEL = "analysis"
|
const val NOTIFICATION_CHANNEL = "analysis"
|
||||||
const val NOTIFICATION_ID = 1
|
const val NOTIFICATION_ID = 1
|
||||||
|
|
||||||
const val KEY_ENTRY_IDS = "entry_ids"
|
|
||||||
const val KEY_FORCE = "force"
|
const val KEY_FORCE = "force"
|
||||||
const val KEY_PROGRESS_TOTAL = "progress_total"
|
|
||||||
const val KEY_PROGRESS_OFFSET = "progress_offset"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package deckers.thibault.aves.channel.calls
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.work.ExistingWorkPolicy
|
import androidx.work.ExistingWorkPolicy
|
||||||
import androidx.work.OneTimeWorkRequest
|
|
||||||
import androidx.work.OneTimeWorkRequestBuilder
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.WorkInfo
|
import androidx.work.WorkInfo
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
|
@ -39,7 +38,7 @@ class AnalysisHandler(private val activity: FlutterActivity, private val onAnaly
|
||||||
|
|
||||||
val preferences = activity.getSharedPreferences(AnalysisWorker.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
val preferences = activity.getSharedPreferences(AnalysisWorker.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
||||||
with(preferences.edit()) {
|
with(preferences.edit()) {
|
||||||
putLong(AnalysisWorker.CALLBACK_HANDLE_KEY, callbackHandle)
|
putLong(AnalysisWorker.PREF_CALLBACK_HANDLE_KEY, callbackHandle)
|
||||||
apply()
|
apply()
|
||||||
}
|
}
|
||||||
result.success(true)
|
result.success(true)
|
||||||
|
@ -54,33 +53,24 @@ class AnalysisHandler(private val activity: FlutterActivity, private val onAnaly
|
||||||
|
|
||||||
// can be null or empty
|
// can be null or empty
|
||||||
val allEntryIds = call.argument<List<Int>>("entryIds")
|
val allEntryIds = call.argument<List<Int>>("entryIds")
|
||||||
val progressTotal = allEntryIds?.size ?: 0
|
|
||||||
var progressOffset = 0
|
|
||||||
|
|
||||||
// work `Data` cannot occupy more than 10240 bytes when serialized
|
// work `Data` cannot occupy more than 10240 bytes when serialized
|
||||||
// so we split it when we have a long list of entry IDs
|
// so we save the possibly long list of entry IDs to shared preferences
|
||||||
val chunked = allEntryIds?.chunked(WORK_DATA_CHUNK_SIZE) ?: listOf(null)
|
val preferences = activity.getSharedPreferences(AnalysisWorker.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
||||||
|
with(preferences.edit()) {
|
||||||
fun buildRequest(entryIds: List<Int>?, progressOffset: Int): OneTimeWorkRequest {
|
putStringSet(AnalysisWorker.PREF_ENTRY_IDS_KEY, allEntryIds?.map { it.toString() }?.toSet())
|
||||||
val workData = workDataOf(
|
apply()
|
||||||
AnalysisWorker.KEY_ENTRY_IDS to entryIds?.toIntArray(),
|
|
||||||
AnalysisWorker.KEY_FORCE to force,
|
|
||||||
AnalysisWorker.KEY_PROGRESS_TOTAL to progressTotal,
|
|
||||||
AnalysisWorker.KEY_PROGRESS_OFFSET to progressOffset,
|
|
||||||
)
|
|
||||||
return OneTimeWorkRequestBuilder<AnalysisWorker>().apply { setInputData(workData) }.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var work = WorkManager.getInstance(activity).beginUniqueWork(
|
val workData = workDataOf(
|
||||||
|
AnalysisWorker.KEY_FORCE to force,
|
||||||
|
)
|
||||||
|
|
||||||
|
WorkManager.getInstance(activity).beginUniqueWork(
|
||||||
ANALYSIS_WORK_NAME,
|
ANALYSIS_WORK_NAME,
|
||||||
ExistingWorkPolicy.KEEP,
|
ExistingWorkPolicy.KEEP,
|
||||||
buildRequest(chunked.first(), progressOffset),
|
OneTimeWorkRequestBuilder<AnalysisWorker>().apply { setInputData(workData) }.build(),
|
||||||
)
|
).enqueue()
|
||||||
chunked.drop(1).forEach { entryIds ->
|
|
||||||
progressOffset += WORK_DATA_CHUNK_SIZE
|
|
||||||
work = work.then(buildRequest(entryIds, progressOffset))
|
|
||||||
}
|
|
||||||
work.enqueue()
|
|
||||||
|
|
||||||
attachToActivity()
|
attachToActivity()
|
||||||
result.success(null)
|
result.success(null)
|
||||||
|
@ -106,6 +96,5 @@ class AnalysisHandler(private val activity: FlutterActivity, private val onAnaly
|
||||||
companion object {
|
companion object {
|
||||||
const val CHANNEL = "deckers.thibault/aves/analysis"
|
const val CHANNEL = "deckers.thibault/aves/analysis"
|
||||||
private const val ANALYSIS_WORK_NAME = "analysis_work"
|
private const val ANALYSIS_WORK_NAME = "analysis_work"
|
||||||
private const val WORK_DATA_CHUNK_SIZE = 1000
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,21 +127,16 @@ class Analyzer with WidgetsBindingObserver {
|
||||||
Future<void> start(dynamic args) async {
|
Future<void> start(dynamic args) async {
|
||||||
List<int>? entryIds;
|
List<int>? entryIds;
|
||||||
var force = false;
|
var force = false;
|
||||||
var progressTotal = 0, progressOffset = 0;
|
|
||||||
if (args is Map) {
|
if (args is Map) {
|
||||||
entryIds = (args['entryIds'] as List?)?.cast<int>();
|
entryIds = (args['entryIds'] as List?)?.cast<int>();
|
||||||
force = args['force'] ?? false;
|
force = args['force'] ?? false;
|
||||||
progressTotal = args['progressTotal'];
|
|
||||||
progressOffset = args['progressOffset'];
|
|
||||||
}
|
}
|
||||||
await reportService.log('Analyzer start for ${entryIds?.length ?? 'all'} entries, at $progressOffset/$progressTotal');
|
await reportService.log('Analyzer start for ${entryIds?.length ?? 'all'} entries');
|
||||||
_controller?.dispose();
|
_controller?.dispose();
|
||||||
_controller = AnalysisController(
|
_controller = AnalysisController(
|
||||||
canStartService: false,
|
canStartService: false,
|
||||||
entryIds: entryIds,
|
entryIds: entryIds,
|
||||||
force: force,
|
force: force,
|
||||||
progressTotal: progressTotal,
|
|
||||||
progressOffset: progressOffset,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
settings.systemLocalesFallback = await deviceService.getLocales();
|
settings.systemLocalesFallback = await deviceService.getLocales();
|
||||||
|
|
|
@ -106,8 +106,8 @@ class AndroidFileUtils {
|
||||||
if (isScreenshotsPath(dirPath)) return AlbumType.screenshots;
|
if (isScreenshotsPath(dirPath)) return AlbumType.screenshots;
|
||||||
if (isVideoCapturesPath(dirPath)) return AlbumType.videoCaptures;
|
if (isVideoCapturesPath(dirPath)) return AlbumType.videoCaptures;
|
||||||
|
|
||||||
final dir = pContext.split(dirPath).last;
|
final dir = pContext.split(dirPath).lastOrNull;
|
||||||
if (dirPath.startsWith(primaryStorage) && appInventory.isPotentialAppDir(dir)) return AlbumType.app;
|
if (dir != null && dirPath.startsWith(primaryStorage) && appInventory.isPotentialAppDir(dir)) return AlbumType.app;
|
||||||
|
|
||||||
return AlbumType.regular;
|
return AlbumType.regular;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue