-
-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Background
In Issue #3, we introduced strategies to prevent multiple SafeBox
instances from accessing the same blob file. This effort culminated in Issue #10, where SafeBoxBlobFileRegistry
was implemented to enforce singleton-per-file constraint.
However, the solution was enforcement-only. It prevents conflicts but gives no insight into SafeBox's runtime state.
Problem
In non-singleton scenarios (e.g. ViewModel-scoped SafeBox), consumers have no way to know:
- Is SafeBox writing right now?
- Has the SafeBox already been closed?
- Can I safely re-create a new instance for the same file name?
This makes it difficult to support real-world async lifecycles (e.g. heavy writes + rapid screen transitions), making it easy to trigger:
IllegalStateException: SafeBox with filename 'xyz' is already in use
Proposal
1. Introduce SafeBoxGlobalStateObserver
This public API is useful for file-level state tracking:
val listener = object : SafeBoxStateListener {
override fun onStateChanged(state: SafeBoxState) {
// Observe IDLE, WRITING, or CLOSED states
}
}
SafeBoxGlobalStateObserver.addListener("my_prefs", listener)
and remove it when it's no longer in use:
SafeBoxGlobalStateObserver.removeListener("my_prefs", listener)
Listeners that were added to SafeBoxGlobalStateObserver
will outlive its instance, since they observe states by file name, not by their SafeBox instance.
2. Add SafeBoxListener
to SafeBox.create(...)
For per-instance scoping, the SafeBox.create(...)
API will support an optional SafeBoxStateListener
that is automatically disposed during safeBox.close()
.
SafeBox.create(
context = ctx,
fileName = "my_prefs",
listener = SafeBoxStateListener { ... } // instance-scoped
)
This listener follows the lifetime of the SafeBox instance and does not persist after close()
.
Implementation Notes
- Global state observer:
SafeBoxGlobalStateObserver
backed byConcurrentHashMap<String, SafeBoxState>
and listener sets. - File registry:
SafeBoxBlobFileRegistry
remains internal and responsible for enforcing singleton. - State transitions are triggered via registry and SafeBox lifecycle.
- Per-instance listeners do not need manual removal; they follow SafeBox's lifecycle.
- Global listeners must be removed manually to prevent leaks.
- Additionally, a new
closeWhenIdle()
will be introduced to close only when the ongoing write completes (if any).
Sub-issues
Metadata
Metadata
Assignees
Labels
Projects
Status