Skip to content

Commit

Permalink
Merge pull request #2069 from bugsnag/PLAT-12438/threaded-startup
Browse files Browse the repository at this point in the history
Rework startup threading
  • Loading branch information
lemnik authored Sep 9, 2024
2 parents a54441d + f7d5058 commit 1832a25
Show file tree
Hide file tree
Showing 37 changed files with 511 additions and 298 deletions.
15 changes: 15 additions & 0 deletions bugsnag-android-core/api/bugsnag-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,8 @@ public final class com/bugsnag/android/internal/BackgroundTaskService {
public fun <init> ()V
public fun <init> (Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ExecutorService;)V
public synthetic fun <init> (Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ExecutorService;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun execute (Lcom/bugsnag/android/internal/TaskType;Ljava/lang/Runnable;)V
public final fun provider (Lcom/bugsnag/android/internal/TaskType;Lkotlin/jvm/functions/Function0;)Lcom/bugsnag/android/internal/dag/RunnableProvider;
public final fun shutdown ()V
public final fun submitTask (Lcom/bugsnag/android/internal/TaskType;Ljava/lang/Runnable;)Ljava/util/concurrent/Future;
public final fun submitTask (Lcom/bugsnag/android/internal/TaskType;Ljava/util/concurrent/Callable;)Ljava/util/concurrent/Future;
Expand Down Expand Up @@ -999,3 +1001,16 @@ public final class com/bugsnag/android/internal/TaskType : java/lang/Enum {
public static fun values ()[Lcom/bugsnag/android/internal/TaskType;
}

public abstract interface class com/bugsnag/android/internal/dag/Provider {
public abstract fun get ()Ljava/lang/Object;
public abstract fun getOrNull ()Ljava/lang/Object;
}

public abstract class com/bugsnag/android/internal/dag/RunnableProvider : com/bugsnag/android/internal/dag/Provider, java/lang/Runnable {
public fun <init> ()V
public fun get ()Ljava/lang/Object;
public fun getOrNull ()Ljava/lang/Object;
public abstract fun invoke ()Ljava/lang/Object;
public final fun run ()V
}

7 changes: 4 additions & 3 deletions bugsnag-android-core/detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
<ID>LongParameterList:AppDataCollector.kt$AppDataCollector$( appContext: Context, private val packageManager: PackageManager?, private val config: ImmutableConfig, private val sessionTracker: SessionTracker, private val activityManager: ActivityManager?, private val launchCrashTracker: LaunchCrashTracker, private val memoryTrimState: MemoryTrimState )</ID>
<ID>LongParameterList:AppWithState.kt$AppWithState$( binaryArch: String?, id: String?, releaseStage: String?, version: String?, codeBundleId: String?, buildUuid: String?, type: String?, versionCode: Number?, /** * The number of milliseconds the application was running before the event occurred */ var duration: Number?, /** * The number of milliseconds the application was running in the foreground before the * event occurred */ var durationInForeground: Number?, /** * Whether the application was in the foreground when the event occurred */ var inForeground: Boolean?, /** * Whether the application was launching when the event occurred */ var isLaunching: Boolean? )</ID>
<ID>LongParameterList:AppWithState.kt$AppWithState$( config: ImmutableConfig, binaryArch: String?, id: String?, releaseStage: String?, version: String?, codeBundleId: String?, duration: Number?, durationInForeground: Number?, inForeground: Boolean?, isLaunching: Boolean? )</ID>
<ID>LongParameterList:DataCollectionModule.kt$DataCollectionModule$( contextModule: ContextModule, configModule: ConfigModule, systemServiceModule: SystemServiceModule, trackerModule: TrackerModule, bgTaskService: BackgroundTaskService, connectivity: Connectivity, deviceIdStore: Future&lt;DeviceIdStore.DeviceIds?>, memoryTrimState: MemoryTrimState )</ID>
<ID>LongParameterList:DataCollectionModule.kt$DataCollectionModule$( contextModule: ContextModule, configModule: ConfigModule, systemServiceModule: SystemServiceModule, trackerModule: TrackerModule, bgTaskService: BackgroundTaskService, connectivity: Connectivity, deviceIdStore: Provider&lt;DeviceIdStore>, memoryTrimState: MemoryTrimState )</ID>
<ID>LongParameterList:Device.kt$Device$( buildInfo: DeviceBuildInfo, /** * The Application Binary Interface used */ var cpuAbi: Array&lt;String>?, /** * Whether the device has been jailbroken */ var jailbroken: Boolean?, /** * A UUID generated by Bugsnag and used for the individual application on a device */ var id: String?, /** * The IETF language tag of the locale used */ var locale: String?, /** * The total number of bytes of memory on the device */ var totalMemory: Long?, /** * A collection of names and their versions of the primary languages, frameworks or * runtimes that the application is running on */ runtimeVersions: MutableMap&lt;String, Any>? )</ID>
<ID>LongParameterList:DeviceBuildInfo.kt$DeviceBuildInfo$( val manufacturer: String?, val model: String?, val osVersion: String?, val apiLevel: Int?, val osBuild: String?, val fingerprint: String?, val tags: String?, val brand: String?, val cpuAbis: Array&lt;String>? )</ID>
<ID>LongParameterList:DeviceDataCollector.kt$DeviceDataCollector$( private val connectivity: Connectivity, private val appContext: Context, resources: Resources, private val deviceIdStore: Future&lt;DeviceIdStore.DeviceIds?>, private val buildInfo: DeviceBuildInfo, private val dataDirectory: File, private val rootedFuture: Future&lt;Boolean>?, private val bgTaskService: BackgroundTaskService, private val logger: Logger )</ID>
<ID>LongParameterList:DeviceDataCollector.kt$DeviceDataCollector$( private val connectivity: Connectivity, private val appContext: Context, resources: Resources, private val deviceIdStore: Provider&lt;DeviceIdStore.DeviceIds?>, private val buildInfo: DeviceBuildInfo, private val dataDirectory: File, private val rootedFuture: Provider&lt;Boolean>?, private val bgTaskService: BackgroundTaskService, private val logger: Logger )</ID>
<ID>LongParameterList:DeviceWithState.kt$DeviceWithState$( buildInfo: DeviceBuildInfo, jailbroken: Boolean?, id: String?, locale: String?, totalMemory: Long?, runtimeVersions: MutableMap&lt;String, Any>, /** * The number of free bytes of storage available on the device */ var freeDisk: Long?, /** * The number of free bytes of memory available on the device */ var freeMemory: Long?, /** * The orientation of the device when the event occurred: either portrait or landscape */ var orientation: String?, /** * The timestamp on the device when the event occurred */ var time: Date? )</ID>
<ID>LongParameterList:EventFilenameInfo.kt$EventFilenameInfo.Companion$( obj: Any, uuid: String = UUID.randomUUID().toString(), apiKey: String?, timestamp: Long = System.currentTimeMillis(), config: ImmutableConfig, isLaunching: Boolean? = null )</ID>
<ID>LongParameterList:EventInternal.kt$EventInternal$( apiKey: String, logger: Logger, breadcrumbs: MutableList&lt;Breadcrumb> = mutableListOf(), discardClasses: Set&lt;Pattern> = setOf(), errors: MutableList&lt;Error> = mutableListOf(), metadata: Metadata = Metadata(), featureFlags: FeatureFlags = FeatureFlags(), originalError: Throwable? = null, projectPackages: Collection&lt;String> = setOf(), severityReason: SeverityReason = SeverityReason.newInstance(SeverityReason.REASON_HANDLED_EXCEPTION), threads: MutableList&lt;Thread> = mutableListOf(), user: User = User(), redactionKeys: Set&lt;Pattern>? = null )</ID>
Expand Down Expand Up @@ -62,13 +62,14 @@
<ID>SwallowedException:ImmutableConfig.kt$e: Exception</ID>
<ID>SwallowedException:JsonHelperTest.kt$JsonHelperTest$e: IllegalArgumentException</ID>
<ID>SwallowedException:PluginClient.kt$PluginClient$exc: ClassNotFoundException</ID>
<ID>SwallowedException:SharedPrefMigrator.kt$SharedPrefMigrator$e: RuntimeException</ID>
<ID>ThrowsCount:JsonHelper.kt$JsonHelper$fun jsonToLong(value: Any?): Long?</ID>
<ID>TooManyFunctions:ConfigInternal.kt$ConfigInternal : CallbackAwareMetadataAwareUserAwareFeatureFlagAware</ID>
<ID>TooManyFunctions:DeviceDataCollector.kt$DeviceDataCollector</ID>
<ID>TooManyFunctions:EventInternal.kt$EventInternal : FeatureFlagAwareStreamableMetadataAwareUserAware</ID>
<ID>UnusedPrivateProperty:ManifestConfigLoader.kt$ManifestConfigLoader.Companion$private const val LAUNCH_CRASH_THRESHOLD_MS = "$BUGSNAG_NS.LAUNCH_CRASH_THRESHOLD_MS"</ID>
<ID>UnusedPrivateProperty:ThreadStateTest.kt$ThreadStateTest$private val configuration = generateImmutableConfig()</ID>
<ID>UseCheckOrError:BackgroundTaskServiceTest.kt$BackgroundTaskServiceTest$throw IllegalStateException()</ID>
<ID>UseCheckOrError:BackgroundRunnableProviderServiceTest.kt$BackgroundRunnableProviderServiceTest$throw IllegalStateException()</ID>
<ID>UseCheckOrError:BugsnagEventMapper.kt$BugsnagEventMapper$throw IllegalStateException("cannot find json property '$key'")</ID>
<ID>UseCheckOrError:StacktraceSerializationTest.kt$StacktraceSerializationTest.Companion$throw IllegalStateException()</ID>
<ID>UseCheckOrError:SynchronizedStreamableStoreTest.kt$CrashyStreamable$throw IllegalStateException()</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class BugsnagStoreMigratorTest {
filesToMove.forEach { (from, to) ->
val file = File(tmpdir, from).apply { mkdirs() }
val newDir = File(tmpdir, to)
BugsnagStoreMigrator.moveToNewDirectory(tmpdir)
BugsnagStoreMigrator.migrateLegacyFiles(lazyOf(tmpdir))
assertFalse(file.isDirectory)
assertFalse(file.exists())
assertTrue(newDir.isDirectory)
Expand All @@ -47,7 +47,7 @@ class BugsnagStoreMigratorTest {
fun testMoveOneFileToNewDirectory() {
val file = File(tmpdir, "bugsnag-native").apply { mkdirs() }
val newDirFile = File(tmpdir, "bugsnag/native")
BugsnagStoreMigrator.moveToNewDirectory(tmpdir)
BugsnagStoreMigrator.migrateLegacyFiles(lazyOf(tmpdir))
assertFalse(file.isDirectory)
assertFalse(file.exists())
assertTrue(newDirFile.exists())
Expand All @@ -63,7 +63,7 @@ class BugsnagStoreMigratorTest {
}
assertTrue(file.isDirectory)
assertTrue(file.exists())
BugsnagStoreMigrator.moveToNewDirectory(tmpdir)
BugsnagStoreMigrator.migrateLegacyFiles(lazyOf(tmpdir))
assertFalse(newDirFile.isDirectory)
assertFalse(newDirFile.exists())
assertTrue(file.isDirectory)
Expand All @@ -74,7 +74,7 @@ class BugsnagStoreMigratorTest {
fun testDeepPathUndefinedFile() {
val file = File(tmpdir, "test/tes2/test3").apply { mkdirs() }
val newDirFile = File(tmpdir, "bugsnag/test/tes2/test3")
BugsnagStoreMigrator.moveToNewDirectory(tmpdir)
BugsnagStoreMigrator.migrateLegacyFiles(lazyOf(tmpdir))
assertFalse(newDirFile.exists())
assertTrue(file.isDirectory)
assertTrue(file.exists())
Expand All @@ -85,7 +85,7 @@ class BugsnagStoreMigratorTest {
val file = File(tmpdir, "bugsnag-sessions").apply { mkdirs() }
File(file, "test1/tes2/test3").apply { mkdirs() }
val newDirFile = File(tmpdir, "bugsnag/sessions/test1/tes2/test3")
BugsnagStoreMigrator.moveToNewDirectory(tmpdir)
BugsnagStoreMigrator.migrateLegacyFiles(lazyOf(tmpdir))
assertTrue(newDirFile.exists())
assertFalse(file.isDirectory)
assertFalse(file.exists())
Expand All @@ -102,7 +102,7 @@ class BugsnagStoreMigratorTest {
val test1moved = File(tmpdir, "bugsnag/errors/test1")
val test2moved = File(tmpdir, "bugsnag/errors/test2")

BugsnagStoreMigrator.moveToNewDirectory(tmpdir)
BugsnagStoreMigrator.migrateLegacyFiles(lazyOf(tmpdir))
assertFalse(file.isDirectory)
assertFalse(file.exists())
assertFalse(test1From.exists())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ internal class DeviceIdStoreTest {
uuidProvider(0),
nonExistentInternalFile,
uuidProvider(1),
sharedPrefMigrator = ValueFuture(prefMigrator),
sharedPrefMigrator = ValueProvider(prefMigrator),
logger = NoopLogger,
config = generateConfig(true)
)

val loaded = store.call()
val loaded = store.load()

assertEquals(ids[0], loaded?.deviceId)
assertEquals(ids[1], loaded?.internalDeviceId)
Expand All @@ -94,12 +94,12 @@ internal class DeviceIdStoreTest {
uuidProvider(0),
fileInternal,
uuidProvider(1),
ValueFuture(prefMigrator),
ValueProvider(prefMigrator),
logger = NoopLogger,
config = generateConfig(true)
)

val loaded = store.call()
val loaded = store.load()

assertEquals(ids[0], loaded?.deviceId)
assertEquals(ids[1], loaded?.internalDeviceId)
Expand All @@ -118,12 +118,12 @@ internal class DeviceIdStoreTest {
uuidProvider(0),
fileInternal,
uuidProvider(1),
ValueFuture(prefMigrator),
ValueProvider(prefMigrator),
logger = NoopLogger,
config = generateConfig(true)
)

val loaded = store.call()
val loaded = store.load()

assertEquals(ids[0], loaded?.deviceId)
assertEquals(ids[1], loaded?.internalDeviceId)
Expand All @@ -142,7 +142,7 @@ internal class DeviceIdStoreTest {
uuidProvider(2),
fileInternal,
uuidProvider(3),
ValueFuture(prefMigrator),
ValueProvider(prefMigrator),
logger = NoopLogger,
config = generateConfig(true)
)
Expand All @@ -152,13 +152,13 @@ internal class DeviceIdStoreTest {
uuidProvider(0),
fileInternal,
uuidProvider(1),
ValueFuture(prefMigrator),
ValueProvider(prefMigrator),
logger = NoopLogger,
config = generateConfig(true)
)

val loadedA = storeA.call()
val loadedB = storeB.call()
val loadedA = storeA.load()
val loadedB = storeB.load()

// device ID is loaded without writing file
assertEquals(ids[0], loadedA?.deviceId)
Expand Down Expand Up @@ -190,12 +190,12 @@ internal class DeviceIdStoreTest {
uuidProvider(0),
nonReadableInternalFile,
uuidProvider(1),
ValueFuture(prefMigrator),
ValueProvider(prefMigrator),
logger = NoopLogger,
config = generateConfig(true)
)

val loaded = store.call()
val loaded = store.load()
assertNull(loaded)
}

Expand All @@ -210,7 +210,7 @@ internal class DeviceIdStoreTest {
uuidProvider(0),
fileInternal,
uuidProvider(1),
ValueFuture(prefMigrator),
ValueProvider(prefMigrator),
logger = NoopLogger,
config = generateConfig(true)
)
Expand All @@ -225,7 +225,7 @@ internal class DeviceIdStoreTest {

repeat(attempts) {
executor.submit {
store.call()?.deviceId?.let { deviceIds.add(it) }
store.load()?.deviceId?.let { deviceIds.add(it) }
latch.countDown()
}
}
Expand All @@ -247,7 +247,7 @@ internal class DeviceIdStoreTest {
uuidProvider(0),
fileInternal,
uuidProvider(1),
ValueFuture(prefMigrator),
ValueProvider(prefMigrator),
logger = NoopLogger,
config = generateConfig(true)
)
Expand All @@ -257,11 +257,9 @@ internal class DeviceIdStoreTest {
context.getSharedPreferences("com.bugsnag.android", Context.MODE_PRIVATE)
prefs.edit().putString("install.iud", prefsId).commit()

val prefDeviceId = prefMigrator
.apply { call() }
.loadDeviceId(false)
val prefDeviceId = prefMigrator.loadDeviceId(false)

val loaded = store.call()
val loaded = store.load()

val storeDeviceId = loaded?.deviceId
assertEquals(prefsId, storeDeviceId)
Expand All @@ -281,12 +279,12 @@ internal class DeviceIdStoreTest {
uuidProvider(0),
fileInternal,
uuidProvider(1),
sharedPrefMigrator = ValueFuture(prefMigrator),
sharedPrefMigrator = ValueProvider(prefMigrator),
logger = NoopLogger,
config = generateConfig(false)
)

val loaded = store.call()
val loaded = store.load()
assertNull(loaded)
}
}
Loading

0 comments on commit 1832a25

Please sign in to comment.