-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: Investigate initializer errors #69
Changes from 8 commits
75fe055
8c0568a
4b64129
d10925c
b2bb4e7
e80a050
f7666a1
ee6f2e0
c023224
8e5998d
337d91f
fbdf3a9
bbd0d8a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package com.infinum.sentinel.ui.certificates.observer | ||
|
||
import android.content.Context | ||
import android.util.Log | ||
import androidx.annotation.UiThread | ||
import androidx.work.Data | ||
import androidx.work.ListenableWorker | ||
import androidx.work.WorkerFactory | ||
import androidx.work.WorkerParameters | ||
import com.google.common.util.concurrent.ListenableFuture | ||
import com.infinum.sentinel.ui.shared.Constants.Keys.WORKER_CLASS_NAME | ||
import com.infinum.sentinel.ui.shared.Constants.Keys.WORKER_ID | ||
import java.util.concurrent.Executor | ||
import java.util.concurrent.TimeUnit | ||
|
||
/** | ||
* A worker to delegate work requests from within the library to workers | ||
* that require factories with custom dependencies. | ||
*/ | ||
internal class DelegateWorker( | ||
appContext: Context, | ||
parameters: WorkerParameters, | ||
) : ListenableWorker(appContext, parameters) { | ||
|
||
private val workerClassName = | ||
parameters.inputData.getString(WORKER_CLASS_NAME) ?: "" | ||
private val workerId = parameters.inputData.getString(WORKER_ID) | ||
private val delegateWorkerFactory = workerFactories[workerId] | ||
private val delegatedWorker = delegateWorkerFactory?.createWorker(appContext, workerClassName, parameters) | ||
|
||
override fun startWork(): ListenableFuture<Result> { | ||
return if (delegatedWorker != null) { | ||
delegatedWorker.startWork() | ||
} else { | ||
val errorMessage = "No delegateWorker available for $workerId" + | ||
" with workerClassName of $workerClassName. Is the " + | ||
"RouterWorker.workerFactories populated correctly?" | ||
|
||
Log.w("Sentinel", errorMessage) | ||
|
||
val errorData = Data.Builder().putString("Reason", errorMessage).build() | ||
|
||
object : ListenableFuture<Result> { | ||
override fun isDone(): Boolean = true | ||
override fun get(): Result = Result.failure(errorData) | ||
override fun get(timeout: Long, unit: TimeUnit): Result = Result.failure(errorData) | ||
override fun cancel(mayInterruptIfRunning: Boolean): Boolean = false | ||
override fun isCancelled(): Boolean = false | ||
override fun addListener(listener: Runnable, executor: Executor) = listener.run() | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we return an "empty" future instead of throwing an error? Shouldn't throwing an error be safer? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, it is not "empty". It is failure with errorData. We need to return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, but I'm exploring less "silent" ways of this failing. Realistically, it could happen only if we forget to register a worker factory, but that's something we shouldn't allow to end up in a release. I'm trying to figure out how we could make sure to not fail fast and loud :D There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think just exception will do the job? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm open for discussions, but an exception (if it would crash the app) would definitely be more noticeable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we throw exception in this place it will just produce logs, similar to Result.Failure. Because it is running on background thread
But error is defiantly more noticeable in logs There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If things go π₯ at least people will see errors and open issues π
|
||
} | ||
} | ||
|
||
companion object { | ||
const val DELEGATE_WORKER_ID = "com.infinum.sentinel.ui.certificates.observer.CertificateCheckWorker" | ||
|
||
val workerFactories = object : AbstractMutableMap<String, WorkerFactory>() { | ||
|
||
private val backingWorkerMap = mutableMapOf<String, WorkerFactory>() | ||
|
||
@UiThread | ||
override fun put(key: String, value: WorkerFactory): WorkerFactory? { | ||
return backingWorkerMap.put(key, value) | ||
} | ||
|
||
override val entries: MutableSet<MutableMap.MutableEntry<String, WorkerFactory>> | ||
get() = backingWorkerMap.entries | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is Sentinel removing the work manager initializer? Does it even use anything from the work manager?
I'm worried about this because if the app add sentinel they would "hiddenly" remove the initialization of the work manager. Everything would be fine for the apps using custom work manager initialization, but for the apps using the default one, work manager wouldn't be initialized anymore.
I'd be calmer if we would remove this code completely, therefore not removing the work manager initialization, and therefore leaving the work manager setup as it is defined in the apps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look into that option as well. It should work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to double check. You are suggesting to remove this whole part?
Do you then think we should add this to our README as a reminder for users that they will have to do it in their projects?
I will leave the decision to Karlo as he is the owner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'm suggesting that, but not in case users would need to add this to their projects only because they have Sentinel.
I'm suggesting removing this if it is redundant.
The only thing when users should add this is in case they use a work manager in their project.
Does Sentinel even use a work manager? What for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think only usage is in
SentinelWorkManager
class. It is used for certificates checking. Interestingly enough, this is the second time certificates are causing problems π .There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I think that is a problem. Since WorkManager can be initialized only once (next time it throws), any application using Work Manager would fail to supply their own workers and initialize the WorkManager. That means, the application dev has to choose, either to use WorkManager and no Sentinel, or vice-versa.
That's the problem we should investigate further and see how to avoid the clash.