Skip to content

PLT-7497: restructure Marconi with a focus on logging - #212

Draft
ana-pantilie wants to merge 4 commits into
mainfrom
PLT-7497-organize-logging-experiment
Draft

PLT-7497: restructure Marconi with a focus on logging#212
ana-pantilie wants to merge 4 commits into
mainfrom
PLT-7497-organize-logging-experiment

Conversation

@ana-pantilie

Copy link
Copy Markdown
Contributor

Pre-submit checklist:

  • Branch
    • Tests are provided (if possible)
    • Commit sequence broadly makes sense and have useful messages
    • Important changes are reflected in changelog.d of the affected packages
    • Relevant tickets are mentioned in commit messages
  • PR
    • (For external contributions) Corresponding issue exists and is linked in the description
    • Targeting main unless this is a cherry-pick backport
    • Self-reviewed the diff
    • Useful pull request description
    • If relevant, reference the ADR in the PR and reference the PR in the ADR
    • Reviewer requested

@neilmayhew neilmayhew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

My comments and suggestions here are fairly random and untested, so feel free to ignore them if they don't seem like they will work

Comment thread marconi-chain-index/src/Marconi/ChainIndex/Logging.hs Outdated
Comment on lines +67 to +68
-- TODO: this should also throw an exception
logMError = undefined

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I feel like log functions shouldn't be throwing exceptions, despite what we said earlier today about having a unified framework for both.

Perhaps it would be OK to have a function that does both, but have that reflected in the name. Something like logThrowError.

In another system I worked on, we also included a "context" parameter which was just a string that indicated where the error was thrown from. This helped a lot when looking at logs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree, I think we need to have the concrete requirements regarding errors and exceptions in order to make any changes here.

Comment on lines +36 to +38
-- TODO: this function is problematic because it is used both inside the
-- ChainIndexT context and outside to initialize the config
-- see Marconi.ChainIndex.Run.run

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you make the monad be a type parameter m and give it constraints (MonadIO m, MonadUnliftIO m)?

Or have two versions of the function, one of which wraps the other and lives in ChainIndexT?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure about using MonadUnliftIO. If I understand correctly, it looks like we'd be restricting our ChainIndexT monad stack to just having reader capabilites, and I don't have enough knowledge about the domain if we need to worry about this or not.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm, still, for the second solution I believe you end up explicitly implementing the ChainIndexT -> IO transformation. Unfortunately this isn't the only place in the code this transformation is needed I think, not 100% sure yet but wanted to add to my previous comment.

Comment thread marconi-chain-index/src/Marconi/ChainIndex/Types.hs
Comment thread marconi-chain-index/src/Marconi/ChainIndex/Types.hs Outdated
Signed-off-by: Ana Pantilie <ana.pantilie@iohk.io>
Signed-off-by: Ana Pantilie <ana.pantilie@iohk.io>

@neilmayhew neilmayhew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is coming together nicely

Comment on lines +684 to +699
liftIO
. Utils.toException
$ Utils.queryCurrentNodeBlockNo @Void networkId socketPath
let indexers = mapMaybe sequenceA indexerList
coordinator <- liftIO $ initializeCoordinatorFromIndexers securityParam indexingDepth indexers
let indexerDepth =
let SecurityParam s = securityParam
in case indexingDepth of
MinIndexingDepth d -> SecurityParam $ s - d + 1
MaxIndexingDepth -> SecurityParam 1
resumablePoints <-
liftIO $ getStartingPointsFromIndexers indexerDepth currentNodeBlockNo indexers coordinator
let oldestCommonChainPoint = minimum resumablePoints
resumePoint = case cliChainPoint of
C.ChainPointAtGenesis -> oldestCommonChainPoint -- User didn't specify a chain point, use oldest common chain point,
cliCp -> cliCp -- otherwise use what was provided on CLI.

@neilmayhew neilmayhew Oct 25, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think you could avoid some of the uses of liftIO by moving these lines outside of withNodeConnectRetryMarconi. I don't think any of them have to run in ChainIndexerT.

However, maybe you plan to migrate more of these functions to ChainIndexerT eventually, so they can get their parameters from the reader env. In which case, they would need to stay where they are.

mkIndexerStream coordinator
. chainSyncEventStreamLogging
. updateProcessedBlocksMetric
runChainSyncStream = liftIO $ withChainSyncBlockEventStream socketPath networkId [resumePoint] stream

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Now that withChainSyncBlockEventStream runs in MonadIO I don't think you need a liftIO here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Overview of one of the problems encountered in my investigation

chainSyncEventStreamLogging needs to have access to the logging context.

The stream is problematic here because it needs to both be in the ChainIndexT context (as noted above) and in IO because it is run by withChainSyncBlockEventStream. Inside, it uses withAsync on the stream consumer which means that we would need a way to "unlift" the ChainIndexT back to IO.

This brings forward the question of whether we can make ChainIndexT an instance of MonadUnliftIO. This would restrict the monad stack to allow only the current reader capability, and also it does not play well with the ExceptT we have decided to keep (as per @willjgould's investigation).

I believe that there are two possible ways to go on from here:

  1. we make ChainIndexT an instance of MonadUnliftIO and see how it impacts the usage of ExceptT, keeping in mind the restrictions we will impose
  2. we refactor the code in such a way that rids it of how deeply coupled it is with IO now, as Will also suggested; I don't know if this is possible, someone with more knowledge of the business logic should have a better idea than me

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.

2 participants