-
Notifications
You must be signed in to change notification settings - Fork 515
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
Multi-tenancy stale wallet clean up #1692
Merged
swcurran
merged 39 commits into
openwallet-foundation:main
from
sicpa-dlab:feature/multitenant-profile-cache
Jun 22, 2022
Merged
Changes from 29 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
7d88b23
feat: add caching for multi-tenant profiles
dbluhm 0769351
feat: add finalizers to profile impls
dbluhm fd057e2
feat: profile cache only on non askar-profile
dbluhm fdac67c
refactor: conductor iterates through open_profiles
dbluhm 22e05f6
fix: multitenant manager tests
dbluhm ac585c9
fix: askar profile tests
dbluhm 6f613ea
fix: open_profiles should be property
dbluhm ce7ccf1
fix: askar profile tests, profile passed to sesh, txn
dbluhm c3d9886
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm a2e306e
feat: profile cache track open profiles via weakref
dbluhm c32d907
fix: create task for profile finalizer
dbluhm d0e2a6d
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm 3528409
style: black fixes
dbluhm f424dbe
fix: prevent circular references from breaking cache
dbluhm a7b5f84
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm a091c63
feat: rework multitenancy-config arg
dbluhm 2ffd521
fix: parsing multiple multitenancy-config options
dbluhm b5b0937
fix: multitenancy config json parsing and tests
dbluhm 569a0ca
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm 1c21804
test: askar profile finalizer
dbluhm 108ecab
refactor: indy test profile by pytest convention
dbluhm 2e80b29
test: indy sdk profile finalizer
dbluhm 9cfbcda
test: cache_size parsing
dbluhm 0422d8a
test: dispatcher responder context weak ref
dbluhm 94b0c3e
test: rescuing still open profile from eviction
dbluhm a9402f4
test: askar profile manager open profiles
dbluhm 625b276
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm 4a5f65d
fix: self.manager for mocking methods in tests
dbluhm 4bf26e5
test: admin responder profile expired
dbluhm e84b3f8
feat: askar profiles don't need finalizers
dbluhm 96e715c
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm df75214
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm e3c8a10
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm 20d753b
fix: oddities and typos
dbluhm da236fd
fix: add key_derivation_method help text back in
dbluhm 9575d07
fix: missing async marks for pytest
dbluhm b018ba8
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm 537425e
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm 5af0ae2
Merge branch 'main' into feature/multitenant-profile-cache
dbluhm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,96 @@ | ||
import asyncio | ||
import logging | ||
import pytest | ||
|
||
from asynctest import TestCase as AsyncTestCase, mock | ||
from asynctest import mock | ||
|
||
from ...askar.profile import AskarProfile | ||
from ...config.injection_context import InjectionContext | ||
|
||
from .. import profile as test_module | ||
|
||
|
||
class TestProfile(AsyncTestCase): | ||
@mock.patch("aries_cloudagent.askar.store.AskarOpenStore") | ||
async def test_init_success(self, AskarOpenStore): | ||
askar_profile = AskarProfile( | ||
AskarOpenStore, | ||
) | ||
|
||
assert askar_profile.opened == AskarOpenStore | ||
|
||
@mock.patch("aries_cloudagent.askar.store.AskarOpenStore") | ||
async def test_remove_success(self, AskarOpenStore): | ||
openStore = AskarOpenStore | ||
context = InjectionContext() | ||
profile_id = "profile_id" | ||
context.settings = { | ||
"multitenant.wallet_type": "askar-profile", | ||
"wallet.askar_profile": profile_id, | ||
"ledger.genesis_transactions": mock.MagicMock(), | ||
} | ||
askar_profile = AskarProfile(openStore, context) | ||
remove_profile_stub = asyncio.Future() | ||
remove_profile_stub.set_result(True) | ||
openStore.store.remove_profile.return_value = remove_profile_stub | ||
|
||
await askar_profile.remove() | ||
|
||
openStore.store.remove_profile.assert_called_once_with(profile_id) | ||
|
||
@mock.patch("aries_cloudagent.askar.store.AskarOpenStore") | ||
async def test_remove_profile_not_removed_if_wallet_type_not_askar_profile( | ||
self, AskarOpenStore | ||
): | ||
openStore = AskarOpenStore | ||
context = InjectionContext() | ||
context.settings = {"multitenant.wallet_type": "basic"} | ||
askar_profile = AskarProfile(openStore, context) | ||
|
||
await askar_profile.remove() | ||
|
||
openStore.store.remove_profile.assert_not_called() | ||
|
||
@pytest.mark.asyncio | ||
async def test_profile_manager_transaction(self): | ||
profile = "profileId" | ||
|
||
with mock.patch("aries_cloudagent.askar.profile.AskarProfile") as AskarProfile: | ||
askar_profile = AskarProfile(None, True) | ||
askar_profile_transaction = mock.MagicMock() | ||
askar_profile.store.transaction.return_value = askar_profile_transaction | ||
askar_profile.context.settings.get.return_value = profile | ||
|
||
transactionProfile = test_module.AskarProfileSession(askar_profile, True) | ||
|
||
assert transactionProfile._opener == askar_profile_transaction | ||
askar_profile.context.settings.get.assert_called_once_with( | ||
"wallet.askar_profile" | ||
) | ||
askar_profile.store.transaction.assert_called_once_with(profile) | ||
|
||
@pytest.mark.asyncio | ||
async def test_profile_manager_store(self): | ||
profile = "profileId" | ||
|
||
with mock.patch("aries_cloudagent.askar.profile.AskarProfile") as AskarProfile: | ||
askar_profile = AskarProfile(None, False) | ||
askar_profile_session = mock.MagicMock() | ||
askar_profile.store.session.return_value = askar_profile_session | ||
askar_profile.context.settings.get.return_value = profile | ||
|
||
sessionProfile = test_module.AskarProfileSession(askar_profile, False) | ||
|
||
assert sessionProfile._opener == askar_profile_session | ||
askar_profile.context.settings.get.assert_called_once_with( | ||
"wallet.askar_profile" | ||
) | ||
askar_profile.store.session.assert_called_once_with(profile) | ||
@pytest.fixture | ||
def open_store(): | ||
yield mock.MagicMock() | ||
|
||
|
||
async def test_init_success(open_store): | ||
askar_profile = AskarProfile( | ||
open_store, | ||
) | ||
|
||
assert askar_profile.opened == open_store | ||
|
||
|
||
async def test_remove_success(open_store): | ||
openStore = open_store | ||
context = InjectionContext() | ||
profile_id = "profile_id" | ||
context.settings = { | ||
"multitenant.wallet_type": "askar-profile", | ||
"wallet.askar_profile": profile_id, | ||
"ledger.genesis_transactions": mock.MagicMock(), | ||
} | ||
askar_profile = AskarProfile(openStore, context, profile_id=profile_id) | ||
remove_profile_stub = asyncio.Future() | ||
remove_profile_stub.set_result(True) | ||
openStore.store.remove_profile.return_value = remove_profile_stub | ||
|
||
await askar_profile.remove() | ||
|
||
openStore.store.remove_profile.assert_called_once_with(profile_id) | ||
|
||
|
||
async def test_remove_profile_not_removed_if_wallet_type_not_askar_profile(open_store): | ||
openStore = open_store | ||
context = InjectionContext() | ||
context.settings = {"multitenant.wallet_type": "basic"} | ||
askar_profile = AskarProfile(openStore, context) | ||
|
||
await askar_profile.remove() | ||
|
||
openStore.store.remove_profile.assert_not_called() | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_profile_manager_transaction(): | ||
profile = "profileId" | ||
|
||
with mock.patch("aries_cloudagent.askar.profile.AskarProfile") as AskarProfile: | ||
askar_profile = AskarProfile(None, True, profile_id=profile) | ||
askar_profile.profile_id = profile | ||
askar_profile_transaction = mock.MagicMock() | ||
askar_profile.store.transaction.return_value = askar_profile_transaction | ||
|
||
transactionProfile = test_module.AskarProfileSession(askar_profile, True) | ||
|
||
assert transactionProfile._opener == askar_profile_transaction | ||
askar_profile.store.transaction.assert_called_once_with(profile) | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_profile_manager_store(): | ||
profile = "profileId" | ||
|
||
with mock.patch("aries_cloudagent.askar.profile.AskarProfile") as AskarProfile: | ||
askar_profile = AskarProfile(None, False, profile_id=profile) | ||
askar_profile.profile_id = profile | ||
askar_profile_session = mock.MagicMock() | ||
askar_profile.store.session.return_value = askar_profile_session | ||
|
||
sessionProfile = test_module.AskarProfileSession(askar_profile, False) | ||
|
||
assert sessionProfile._opener == askar_profile_session | ||
askar_profile.store.session.assert_called_once_with(profile) | ||
|
||
|
||
def test_finalizer(open_store, caplog): | ||
def _smaller_scope(): | ||
askar_profile = AskarProfile(open_store) | ||
askar_profile.finalizer() | ||
|
||
with caplog.at_level(logging.DEBUG): | ||
_smaller_scope() | ||
|
||
assert "finalizer called" in caplog.text |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
It's nice but not necessary to close the store this way, as the library has its own finalizers. With multiple profile instances potentially referencing the same Store it would probably not be correct to close the store when a single profile is closed, either.