Skip to content

Conversation

TimoGlastra
Copy link
Contributor

Adds support for using multiple indy ledgers simultaneously. I'd really like some input on the approach before wrapping up and merging.

  • Only supports multiple ledgers for reading, writing to the ledger still only supports one pool, which is currently always first configured pool.
  • genesisPath, poolName and genesisTransactions in the InitConfig are replaced by the indyLedgers array property with the following structure: (@MosCD3)
interface IndyPoolConfig {
  genesisPath?: string
  genesisTransactions?: string
  id: string
  isProduction: boolean
}

Before each read operation in IndyLedgerService a new method is called, IndyPoolService.getPoolForDid. The method will, if successful, return the pool that should be used for the operation. The process is a follows:

  1. If no pools are configured, an error will be thrown immediately
  2. loop through all configured pools and performs a getNymRequest.
    1. If one of the responses is not successful, and is other than LedgerNotFound, an error will be thrown immediately. This means if one requests fails with an unknown error, the process fails. This is to prevent an incorrect pool from being returned.
    2. If all pools couldn't find the did, a LedgerNotFoundError will be thrown
  3. A divide between production and non production ledgers is made.
    1. If there is one or more successful responses from production ledgers, this is assigned as the remaining group
    2. If there are no successful responses from production ledgers, and there are one or more successful responses from non production ledgers, the non production results are assigned as the remaining group.
  4. If there is only one response in the remaining group, return the pool associated with the response
  5. Loop through all remaining responses and check for each if the did is self certifying.
    1. If exactly one of the DIDs is self certifying, return the pool associated with it.
  6. If there's still no pool selected, sort all items in the remaning group based on txnTime. The pool associated with the earliest txnTime will be returned.

@swcurran @shaangill025 I'm not so sure on 6. in the process. From the google document I understand that the txnTime is not the same as the time the DID was registered. In the HackMD document from @shaangill025 (https://hackmd.io/BVye073CTiqgNEMXxDeVdQ) the following step is described: "return production ledger with oldest/min datetime". Where does the oldest/min datetime property come from? I'd rather not have a service that tracks DIDs that are on multiple ledgers, and would be inclined to just throw an error instead that the DID couldn't be resolved.

Signed-off-by: Timo Glastra <timo@animo.id>
@TimoGlastra TimoGlastra requested review from a team, swcurran and shaangill025 September 26, 2021 21:29
@codecov-commenter
Copy link

codecov-commenter commented Sep 26, 2021

Codecov Report

Merging #474 (558adfa) into main (af39ad5) will increase coverage by 0.60%.
The diff coverage is 94.70%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #474      +/-   ##
==========================================
+ Coverage   85.79%   86.39%   +0.60%     
==========================================
  Files         254      266      +12     
  Lines        5525     5726     +201     
  Branches      892      920      +28     
==========================================
+ Hits         4740     4947     +207     
+ Misses        784      778       -6     
  Partials        1        1              
Impacted Files Coverage Δ
packages/core/src/types.ts 100.00% <ø> (ø)
packages/core/src/modules/ledger/IndyPool.ts 84.05% <84.05%> (ø)
...e/src/modules/ledger/services/IndyLedgerService.ts 85.71% <90.90%> (+6.19%) ⬆️
packages/core/src/agent/AgentConfig.ts 94.33% <100.00%> (+3.11%) ⬆️
packages/core/src/cache/CacheRecord.ts 100.00% <100.00%> (ø)
packages/core/src/cache/CacheRepository.ts 100.00% <100.00%> (ø)
packages/core/src/cache/PersistedLruCache.ts 100.00% <100.00%> (ø)
packages/core/src/cache/index.ts 100.00% <100.00%> (ø)
...kages/core/src/modules/ledger/error/LedgerError.ts 100.00% <100.00%> (ø)
...c/modules/ledger/error/LedgerNotConfiguredError.ts 100.00% <100.00%> (ø)
... and 9 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update af39ad5...558adfa. Read the comment docs.

@MosCD3
Copy link
Contributor

MosCD3 commented Sep 27, 2021

@TimoGlastra I like the approach since multiple ledger pools are mainly needed mostly in POC and development phases.

Copy link
Contributor

@berendsliedrecht berendsliedrecht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just have some minor points, but overall it seems good to me. Is multi-ledger-support added in any other framework as described in the document?

Also, this might be worth mentioning in the feature list, it is a very nice feature.

@TimoGlastra TimoGlastra linked an issue Sep 29, 2021 that may be closed by this pull request
@TimoGlastra
Copy link
Contributor Author

Things to add:

  • Initially do not throw if one of the ledgers errors out.
  • option to throw error when one of the pools throws a ledger
  • caching

Signed-off-by: Timo Glastra <timo@animo.id>
Signed-off-by: Timo Glastra <timo@animo.id>
Signed-off-by: Timo Glastra <timo@animo.id>
Signed-off-by: Timo Glastra <timo@animo.id>
Copy link
Contributor

@JamesKEbert JamesKEbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great @TimoGlastra! I left minor requests.. and I think there may have been some tweaks still required from the last AFJ call?

Comment on lines +13 to +15
import { LedgerError } from '../error/LedgerError'
import { LedgerNotConfiguredError } from '../error/LedgerNotConfiguredError'
import { LedgerNotFoundError } from '../error/LedgerNotFoundError'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we place all the errors within one file? It seems like it's a little more overhead/verbose to have them separate for less value from my POV?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I'll do it in a follow up PR to keep consistency.In the rest of the codebase all errors have their own file

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome 🔥

Signed-off-by: Timo Glastra <timo@animo.id>
Signed-off-by: Timo Glastra <timo@animo.id>
@TimoGlastra
Copy link
Contributor Author

Resolved feedback from AFJ call and PR.

Ready for final review

Copy link
Contributor

@JamesKEbert JamesKEbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, great work here, I appreciate the efforts put into this!

Comment on lines 231 to 235
- `indyLedgers`: The indy ledgers to connect to. This is an array of objects with the following properties. Either `genesisPath` or `genesisTransactions` must be set, but not both.
- `id`\*: The id (or name) of the ledger, also used as the pool name
- `isProduction`\*: Whether the ledger is a production ledger. This is used by the pool selector algorithm to know which ledger to use for certain interactions (i.e. prefer production ledgers over non-production ledgers)
- `genesisPath`: The path to the genesis file to use for connecting to an Indy ledger.
- `genesisTransactions`: String of genesis transactions to use for connecting to an Indy ledger.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potentially something important to highlight here would be that the order of the ledgers in the array determines their priority (after production vs non-production)? As indicated in a comment in the IndyPoolService:

We take the first value as we take the order in the indyLedgers config as
the order of preference of ledgers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes great point. I'll update it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some documentation around ledgers

Signed-off-by: Timo Glastra <timo@animo.id>
Signed-off-by: Timo Glastra <timo@animo.id>
Signed-off-by: Timo Glastra <timo@animo.id>
@TimoGlastra TimoGlastra merged commit 47149bc into openwallet-foundation:main Oct 20, 2021
@TimoGlastra TimoGlastra deleted the feat/multi-ledger-support branch October 20, 2021 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Supporting multiple genesis file
7 participants