Skip to content

Commit

Permalink
Merge branch '364_graph_merge_error_because_trimmed'
Browse files Browse the repository at this point in the history
  • Loading branch information
agentm committed Jan 20, 2024
2 parents f88285d + e1dcbe2 commit 79b3a66
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
26 changes: 24 additions & 2 deletions src/lib/ProjectM36/ReferencedTransactionIds.hs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{-# LANGUAGE FlexibleInstances #-}
module ProjectM36.ReferencedTransactionIds where
import ProjectM36.Base
import ProjectM36.Error
import qualified ProjectM36.Transaction as T
import ProjectM36.RelationalExpression
import qualified Data.Map as M
import qualified Data.Set as S
import Control.Monad (foldM)

type TransactionIds = S.Set TransactionId

Expand Down Expand Up @@ -112,6 +116,24 @@ instance ReferencedTransactionIds DatabaseContext where
]

instance ReferencedTransactionIds RelationVariables where
referencedTransactionIds relVars =
S.unions (referencedTransactionIds <$> M.elems relVars)
referencedTransactionIds relVars =
S.unions (referencedTransactionIds <$> M.elems relVars)

-- | Recurse relvars references and transaction parents to extract a subset of relevant transactions.
-- probably could do some trimming of transactions that are not referenced by relvars, but that is rare, so probably of not much benefit
-- should be trim merge parents that don't contribute to the relvars? maybe
referencedTransactionIdsForTransaction :: Transaction -> TransactionGraph -> Either RelationalError (S.Set Transaction)
referencedTransactionIdsForTransaction trans graph
| parentIds == T.rootParent = pure (S.singleton trans)
| otherwise =
foldM folder (S.singleton trans) parentIds
where
parentIds = parents (transactionInfo trans)
folder acc transId' = do
trans' <- transactionForId transId' graph
transSet <- referencedTransactionIdsForTransaction trans' graph
pure (S.union acc transSet)




27 changes: 18 additions & 9 deletions src/lib/ProjectM36/TransactionGraph.hs
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,8 @@ subGraphOfFirstCommonAncestor origGraph resultHeads currentTrans' goalTrans trav
-- we union all the relevant path transactions together, but we are missing any transactions which these transaction may reference. To make a valid transaction graph, we must include these referenced transactions.
let openSet = S.unions (traverseSet : pathsFound)
transactionIncluder acc trans = do
let allTids = referencedTransactionIds (concreteDatabaseContext trans)
allTrans <- mapM (`transactionForId` origGraph) (S.toList allTids)
pure $ S.unions (S.singleton trans : S.fromList allTrans : [acc])
allTrans <- referencedTransactionIdsForTransaction trans origGraph
pure $ S.union allTrans acc
closedTransactionSet <- foldM transactionIncluder mempty (S.toList openSet)
Right (TransactionGraph resultHeads closedTransactionSet)
where
Expand Down Expand Up @@ -447,6 +446,8 @@ mergeTransactions stamp' newId parentId mergeStrategy (headNameA, headNameB) = d
let subHeads = M.filterWithKey (\k _ -> k `elem` [headNameA, headNameB]) (transactionHeadsForGraph graph)
-- is this an optimization???
subGraph <- runE $ subGraphOfFirstCommonAncestor graph subHeads transA transB S.empty
_ <- runE $ validateConnectivity subGraph

subGraph' <- runE $ filterSubGraph subGraph subHeads
-- we cannot cut the transaction graph away only to "relevant" transactions because transactions can reference other transactions via relvar expressions
mergedTrans <- local (const (freshGraphRefRelationalExprEnv Nothing subGraph')) $
Expand All @@ -463,18 +464,20 @@ mergeTransactions stamp' newId parentId mergeStrategy (headNameA, headNameB) = d
pure (newDiscon, newGraph')

--TEMPORARY COPY/PASTE
showTransactionStructureX :: Transaction -> TransactionGraph -> String
showTransactionStructureX trans graph = headInfo ++ " " ++ show (transactionId trans) ++ " " ++ parentTransactionsInfo
showTransactionStructureX :: Bool -> Transaction -> TransactionGraph -> String
showTransactionStructureX showRelVars trans graph = headInfo ++ " " ++ show (transactionId trans) ++ " " ++ parentTransactionsInfo ++ relVarsInfo
where
relVarsInfo | showRelVars == False = ""
| otherwise = "\n" <> concatMap show (M.toList (relationVariables (concreteDatabaseContext trans)))
headInfo = maybe "" show (headNameForTransaction trans graph)
parentTransactionsInfo = if isRootTransaction trans then "root" else case parentTransactions trans graph of
Left err -> show err
Right parentTransSet -> concat $ S.toList $ S.map (show . transactionId) parentTransSet

showGraphStructureX :: TransactionGraph -> String
showGraphStructureX graph@(TransactionGraph heads transSet) = headsInfo ++ S.foldr folder "" transSet
showGraphStructureX :: Bool -> TransactionGraph -> String
showGraphStructureX showRelVars graph@(TransactionGraph heads transSet) = headsInfo ++ S.foldr folder "" transSet
where
folder trans acc = acc ++ showTransactionStructureX trans graph ++ "\n"
folder trans acc = acc ++ showTransactionStructureX showRelVars trans graph ++ "\n"
headsInfo = show $ M.map transactionId heads

-- | After splicing out a subgraph, run it through this function to remove references to transactions which are not in the subgraph.
Expand Down Expand Up @@ -637,4 +640,10 @@ validateMerkleHashes graph =
Left err -> err : acc
_ -> acc


-- | Ensure that referenced transactions remain in the graph.
validateConnectivity :: TransactionGraph -> Either RelationalError TransactionGraph
validateConnectivity graph = do
let validateTrans trans =
mapM_ (`transactionForId` graph) (referencedTransactionIds (concreteDatabaseContext trans))
mapM_ validateTrans (transactionsForGraph graph)
pure graph

0 comments on commit 79b3a66

Please sign in to comment.