On Sat, Aug 01, 2015 at 03:08:47AM +0300, Nikita Karetnikov wrote: > > Oh, wow. Thanks for the tip. I will probably do that. Even after > > spending a few hours on this esqueleto, it will still save me time to > > switch. > > > > Just gotta figure out how to share database connection information... > > Is it really that bad? If it's a major slowdown, just go ahead, but > paste what you've tried. Also, I'd suggest moving a subselect into a > separate Haskell function, even with strings.
Here's what is happening so far:
-- | Find underfunded patrons.
-- This function is used after something may have broken the invariant that
-- all funded pledges are covered by the patron's account balance. It
returns
-- pertinent information about each underfunded pledge.
--
underfundedUsers :: (MonadIO m, Functor m)
=> ProjectId
-> SqlPersistT m [Underfunded]
underfundedUsers projId = do
-- the inner query
totalOutlays <- fmap processOutlayRows $
select $
from $ \(pl `InnerJoin` pr `InnerJoin` u `InnerJoin` ac) -> do
on_ $ ac ^. AccountId ==. u ^. UserAccount
on_ $ u ^. UserId ==. pl ^. PledgeUser
on_ $ pr ^. ProjectId ==. pl ^. PledgeProject
where_ $ pl ^. PledgeFundedShares >. val 0
groupBy $ (u ^. UserId)
return (u ^. UserId
,sum_ (($*.) (pr ^. ProjectShareValue)
(pl ^. PledgeFundedShares))
)
let process' = processIntermediateRows totalOutlays
intemediate <- fmap process' $
select $
from $ \(pl `InnerJoin` u `InnerJoin` ac `InnerJoin` pr) -> do
on_ $ pr ^. ProjectId ==. pl ^. PledgeProject
on_ $ ac ^. AccountId ==. u ^. UserAccount
on_ $ u ^. UserId ==. pl ^. PledgeUser
return (u ^. UserId
,ac ^. AccountBalance
,pl ^. PledgeFundedShares
,pr ^. ProjectId
,pr ^. ProjectShareValue
,ac ^. AccountId)
where
-- | Just cleans up types and removes rows that returned Nothing
-- for the sum. (There actually shouldn't be any because of the inner
-- join, but whatevs.)
processOutlayRows :: [(Value UserId, Value (Maybe Milray))]
-> Map UserId Milray
processOutlayRows = M.fromList
. catMaybes
. map sequence -- 'lift' the Maybe
. unwrapValues
-- | Primarily calculates the "available balance" for each pledge.
-- That is defined, for each pledge, as the difference between the
-- patron's total balance and the sum of the outlay going to the
-- patron's *other* pledges.
processIntermediateRows :: Map UserId Milray
-> [(Value UserId
,Value Milray
,Value Int64
,Value ProjectId
,Value Milray
,Value AccountId)]
-> [Underfunded]
processIntermediateRows totalOutlays =
map ( (\(u, a, p, v) -> Underfunded u a p v))
. map getAvailable
. unwrapValues
)
where
getAvailable (UserId, Milray, Int64, ProjectId, Milray, AccountId) =
-- XXX TODO
undefined
> Note that with esqueleto, if you change the schema, you'll get a compile
> time warning. While with strings, it'll happen at runtime.
True, but I have to accept that risk right now. Tests will help.
signature.asc
Description: Digital signature
_______________________________________________ Dev mailing list [email protected] https://lists.snowdrift.coop/mailman/listinfo/dev
