Skip to content

Commit bb807ae

Browse files
committed
Try pipelining more queries
1 parent 9a9b531 commit bb807ae

File tree

15 files changed

+219
-189
lines changed

15 files changed

+219
-189
lines changed

src/Share/Backend.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ mkTermDefinition termPPED width r docs tm = do
142142
docs
143143

144144
termListEntry ::
145-
(PG.QueryM m) =>
145+
(PG.QueryM m e) =>
146146
Type Symbol Ann ->
147147
ExactName NameSegment V2Referent.Referent ->
148148
m (Backend.TermEntry Symbol Ann)
@@ -160,7 +160,7 @@ termListEntry typ (ExactName nameSegment ref) = do
160160
}
161161

162162
typeListEntry ::
163-
(PG.QueryM m) =>
163+
(PG.QueryM m e) =>
164164
ExactName NameSegment Reference ->
165165
m Backend.TypeEntry
166166
typeListEntry (ExactName nameSegment ref) = do
@@ -176,7 +176,7 @@ typeListEntry (ExactName nameSegment ref) = do
176176
}
177177

178178
getTermTag ::
179-
(PG.QueryM m, Var v) =>
179+
(PG.QueryM m e, Var v) =>
180180
V2Referent.Referent ->
181181
Type v Ann ->
182182
m TermTag
@@ -199,7 +199,7 @@ getTermTag r termType = do
199199
| otherwise -> Plain
200200

201201
getTypeTag ::
202-
(PG.QueryM m) =>
202+
(PG.QueryM m e) =>
203203
Reference.TypeReference ->
204204
m TypeTag
205205
getTypeTag r = do

src/Share/Codebase.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,10 @@ expectTypeOfReferents :: Traversal s t V2.Referent (V1.Type Symbol Ann) -> s ->
278278
expectTypeOfReferents trav s = do
279279
s & trav %%~ expectTypeOfReferent
280280

281-
expectDeclKind :: (PG.QueryM m) => Reference.TypeReference -> m CT.ConstructorType
281+
expectDeclKind :: (PG.QueryM m e) => Reference.TypeReference -> m CT.ConstructorType
282282
expectDeclKind r = loadDeclKind r `whenNothingM` (unrecoverableError (InternalServerError "missing-decl-kind" $ "Couldn't find the decl kind of " <> tShow r))
283283

284-
expectDeclKindsOf :: (PG.QueryM m) => Traversal s t Reference.TypeReference CT.ConstructorType -> s -> m t
284+
expectDeclKindsOf :: (PG.QueryM m e) => Traversal s t Reference.TypeReference CT.ConstructorType -> s -> m t
285285
expectDeclKindsOf trav s = do
286286
s
287287
& unsafePartsOf trav %%~ \refs -> do
@@ -290,10 +290,10 @@ expectDeclKindsOf trav s = do
290290
(r, Nothing) -> unrecoverableError (InternalServerError "missing-decl-kind" $ "Couldn't find the decl kind of " <> tShow r)
291291
(_, Just ct) -> pure ct
292292

293-
loadDeclKind :: (PG.QueryM m) => V2.TypeReference -> m (Maybe CT.ConstructorType)
293+
loadDeclKind :: (PG.QueryM m e) => V2.TypeReference -> m (Maybe CT.ConstructorType)
294294
loadDeclKind = loadDeclKindsOf id
295295

296-
loadDeclKindsOf :: (PG.QueryM m) => Traversal s t Reference.TypeReference (Maybe CT.ConstructorType) -> s -> m t
296+
loadDeclKindsOf :: (PG.QueryM m e) => Traversal s t Reference.TypeReference (Maybe CT.ConstructorType) -> s -> m t
297297
loadDeclKindsOf trav s =
298298
s
299299
& unsafePartsOf trav %%~ \refs -> do

src/Share/Postgres.hs

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{-# LANGUAGE ConstraintKinds #-}
22
{-# LANGUAGE DeriveAnyClass #-}
3+
{-# LANGUAGE FunctionalDependencies #-}
34
{-# LANGUAGE ImpredicativeTypes #-}
45
{-# LANGUAGE LiberalTypeSynonyms #-}
56
{-# LANGUAGE TypeFamilies #-}
67
{-# LANGUAGE TypeOperators #-}
8+
{-# LANGUAGE UndecidableInstances #-}
79

810
-- | Postgres helpers
911
module Share.Postgres
@@ -42,7 +44,6 @@ module Share.Postgres
4244
tryRunSessionWithPool,
4345
unliftSession,
4446
defaultIsolationLevel,
45-
pipelined,
4647
pFor,
4748
pFor_,
4849

@@ -122,10 +123,6 @@ instance MonadError e (Transaction e) where
122123
newtype Pipeline e a = Pipeline {unPipeline :: Hasql.Pipeline.Pipeline (Either (TransactionError e) a)}
123124
deriving (Functor, Applicative) via (Compose Hasql.Pipeline.Pipeline (Either (TransactionError e)))
124125

125-
-- | Run a pipeline in a transaction
126-
pipelined :: Pipeline e a -> Transaction e a
127-
pipelined p = Transaction (Hasql.pipeline (unPipeline p))
128-
129126
pFor :: (Traversable f) => f a -> (a -> Pipeline e b) -> Transaction e (f b)
130127
pFor f p = pipelined $ for f p
131128

@@ -319,81 +316,106 @@ runSessionOrRespondError :: (HasCallStack, ToServerError e, Loggable e) => Sessi
319316
runSessionOrRespondError t = tryRunSession t >>= either respondError pure
320317

321318
-- | Represents anywhere we can run a statement
322-
class (Applicative m) => QueryA m where
319+
class (Applicative m) => QueryA m e | m -> e where
323320
statement :: q -> Hasql.Statement q r -> m r
324321

325322
-- | Fail the transaction and whole request with an unrecoverable server error.
326-
unrecoverableError :: (HasCallStack, ToServerError e, Loggable e, Show e) => e -> m a
323+
unrecoverableError :: (HasCallStack, ToServerError x, Loggable x, Show x) => x -> m a
324+
325+
throwErr :: (ToServerError e, Loggable e, Show e) => e -> m a
327326

328-
class (Monad m, QueryA m) => QueryM m where
327+
pipelined :: Pipeline e a -> m a
328+
329+
class (Monad m, QueryA m e) => QueryM m e | m -> e where
329330
-- | Allow running IO actions in a transaction. These actions may be run multiple times if
330331
-- the transaction is retried.
331332
transactionUnsafeIO :: IO a -> m a
332333

333-
instance QueryA (Transaction e) where
334+
instance QueryA (Transaction e) e where
334335
statement q s = do
335336
transactionStatement q s
336337

338+
throwErr = throwError
339+
340+
pipelined p = Transaction (Hasql.pipeline (unPipeline p))
341+
337342
unrecoverableError e = Transaction (pure (Left (Unrecoverable (someServerError e))))
338343

339-
instance QueryM (Transaction e) where
344+
instance QueryM (Transaction e) e where
340345
transactionUnsafeIO io = Transaction (Right <$> liftIO io)
341346

342-
instance QueryA (Session e) where
347+
instance QueryA (Session e) e where
343348
statement q s = do
344349
lift $ Session.statement q s
345350

351+
throwErr = throwError . Err
352+
353+
pipelined p = do
354+
ExceptT $ Hasql.pipeline (unPipeline p)
355+
346356
unrecoverableError e = throwError (Unrecoverable (someServerError e))
347357

348-
instance QueryM (Session e) where
358+
instance QueryM (Session e) e where
349359
transactionUnsafeIO io = lift $ liftIO io
350360

351-
instance QueryA (Pipeline e) where
361+
instance QueryA (Pipeline e) e where
352362
statement q s = Pipeline (Right <$> Hasql.Pipeline.statement q s)
353363

364+
throwErr = Pipeline . pure . Left . Err
365+
366+
pipelined p = p
367+
354368
unrecoverableError e = Pipeline $ pure (Left (Unrecoverable (someServerError e)))
355369

356-
instance (QueryM m) => QueryA (ReaderT e m) where
370+
instance (QueryM m e) => QueryA (ReaderT r m) e where
357371
statement q s = lift $ statement q s
358372

373+
throwErr = lift . throwErr
374+
375+
pipelined p = lift $ pipelined p
376+
359377
unrecoverableError e = lift $ unrecoverableError e
360378

361-
instance (QueryM m) => QueryM (ReaderT e m) where
379+
instance (QueryM m e) => QueryM (ReaderT r m) e where
362380
transactionUnsafeIO io = lift $ transactionUnsafeIO io
363381

364-
instance (QueryM m) => QueryA (MaybeT m) where
382+
instance (QueryM m e) => QueryA (MaybeT m) e where
365383
statement q s = lift $ statement q s
366384

385+
throwErr = lift . throwErr
386+
387+
pipelined p = lift $ pipelined p
388+
367389
unrecoverableError e = lift $ unrecoverableError e
368390

369-
instance (QueryM m) => QueryM (MaybeT m) where
391+
instance (QueryM m e) => QueryM (MaybeT m) e where
370392
transactionUnsafeIO io = lift $ transactionUnsafeIO io
371393

372394
prepareStatements :: Bool
373395
prepareStatements = True
374396

375-
queryListRows :: forall r m. (Interp.DecodeRow r, QueryM m) => Interp.Sql -> m [r]
397+
queryListRows :: forall r m e. (Interp.DecodeRow r, QueryA m e) => Interp.Sql -> m [r]
376398
queryListRows sql = statement () (Interp.interp prepareStatements sql)
377399

378-
query1Row :: forall r m. (QueryM m) => (Interp.DecodeRow r) => Interp.Sql -> m (Maybe r)
400+
query1Row :: forall r m e. (QueryA m e) => (Interp.DecodeRow r) => Interp.Sql -> m (Maybe r)
379401
query1Row sql = listToMaybe <$> queryListRows sql
380402

381-
query1Col :: forall a m. (QueryM m, Interp.DecodeField a) => Interp.Sql -> m (Maybe a)
403+
query1Col :: forall a m e. (QueryA m e, Interp.DecodeField a) => Interp.Sql -> m (Maybe a)
382404
query1Col sql = listToMaybe <$> queryListCol sql
383405

384-
queryListCol :: forall a m. (QueryM m) => (Interp.DecodeField a) => Interp.Sql -> m [a]
406+
queryListCol :: forall a m e. (QueryA m e) => (Interp.DecodeField a) => Interp.Sql -> m [a]
385407
queryListCol sql = queryListRows @(Interp.OneColumn a) sql <&> coerce @[Interp.OneColumn a] @[a]
386408

387-
execute_ :: (QueryA m) => Interp.Sql -> m ()
409+
execute_ :: (QueryA m e) => Interp.Sql -> m ()
388410
execute_ sql = statement () (Interp.interp prepareStatements sql)
389411

390-
queryExpect1Row :: forall r m. (HasCallStack) => (Interp.DecodeRow r, QueryM m) => Interp.Sql -> m r
412+
queryExpect1Row :: forall r m e. (HasCallStack) => (Interp.DecodeRow r, QueryM m e) => Interp.Sql -> m r
391413
queryExpect1Row sql =
392414
query1Row sql >>= \case
393415
Nothing -> error "queryExpect1Row: expected 1 row, got 0"
394416
Just r -> pure r
395417

396-
queryExpect1Col :: forall a m. (HasCallStack) => (Interp.DecodeField a, QueryM m) => Interp.Sql -> m a
418+
queryExpect1Col :: forall a m e. (HasCallStack) => (Interp.DecodeField a, QueryM m e) => Interp.Sql -> m a
397419
queryExpect1Col sql =
398420
query1Col sql >>= \case
399421
Nothing -> error "queryExpect1Col: expected 1 row, got 0"
@@ -497,7 +519,7 @@ instance Interp.DecodeValue RawBytes where
497519
whenNonEmpty :: forall m f a x. (Monad m, Foldable f, Monoid a) => f x -> m a -> m a
498520
whenNonEmpty f m = if null f then pure mempty else m
499521

500-
timeTransaction :: (QueryM m) => String -> m a -> m a
522+
timeTransaction :: (QueryM m e) => String -> m a -> m a
501523
timeTransaction label ma =
502524
if Debug.shouldDebug Debug.Timing
503525
then do

src/Share/Postgres/Causal/Queries.hs

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import Share.Codebase.Types (CodebaseM)
3434
import Share.Codebase.Types qualified as Codebase
3535
import Share.IDs (UserId)
3636
import Share.Postgres
37+
import Share.Postgres qualified as PG
3738
import Share.Postgres.Causal.Types
3839
import Share.Postgres.Definitions.Queries qualified as Defn
3940
import Share.Postgres.Definitions.Types
@@ -58,7 +59,7 @@ import Unison.NameSegment.Internal as NameSegment
5859
import Unison.Reference qualified as Reference
5960
import Unison.Util.Map qualified as Map
6061

61-
expectCausalNamespace :: (HasCallStack, QueryM m) => CausalId -> m (CausalNamespace m)
62+
expectCausalNamespace :: (HasCallStack, QueryM m e) => CausalId -> m (CausalNamespace m)
6263
expectCausalNamespace causalId =
6364
loadCausalNamespace causalId
6465
`whenNothingM` unrecoverableError (MissingExpectedEntity $ "Expected causal branch for hash:" <> tShow causalId)
@@ -98,7 +99,7 @@ expectPgCausalNamespace causalId =
9899
loadPgCausalNamespace causalId
99100
`whenNothingM` unrecoverableError (MissingExpectedEntity $ "Expected causal branch for causal: " <> tShow causalId)
100101

101-
loadCausalNamespace :: forall m. (QueryM m) => CausalId -> m (Maybe (CausalNamespace m))
102+
loadCausalNamespace :: forall m e. (QueryM m e) => CausalId -> m (Maybe (CausalNamespace m))
102103
loadCausalNamespace causalId = runMaybeT $ do
103104
causalHash <- HashQ.expectCausalHashesByIdsOf id causalId
104105
branchHashId <- HashQ.expectNamespaceIdsByCausalIdsOf id causalId
@@ -139,22 +140,23 @@ expectNamespaceHashByCausalHash causalHash = do
139140
AND EXISTS (SELECT FROM causal_ownership o WHERE o.causal_id = causals.id AND o.user_id = #{codebaseOwner})
140141
|]
141142

142-
expectNamespace :: forall m. (QueryM m) => BranchHashId -> m (Branch m)
143+
expectNamespace :: forall m e. (QueryM m e) => BranchHashId -> m (Branch m)
143144
expectNamespace branchHashId = do
144-
termsAndConstructors <- getTermsAndConstructors branchHashId <&> (traversed . traversed %~ loadTermMetadata)
145-
types <- getTypes branchHashId <&> (traversed . traversed %~ loadTypeMetadata)
146145
patches <- getPatches branchHashId
147146
children <- getChildren branchHashId
148-
pure $
149-
Branch
150-
{ -- (<>) is safe here because no referents will overlap between terms and constructors
151-
terms = termsAndConstructors,
152-
types,
153-
patches,
154-
children
155-
}
147+
pipelined $ do
148+
termsAndConstructors <- getTermsAndConstructors branchHashId <&> (traversed . traversed %~ loadTermMetadata)
149+
types <- getTypes branchHashId <&> (traversed . traversed %~ loadTypeMetadata)
150+
pure $
151+
Branch
152+
{ -- (<>) is safe here because no referents will overlap between terms and constructors
153+
terms = termsAndConstructors,
154+
types,
155+
patches,
156+
children
157+
}
156158
where
157-
getTermsAndConstructors :: BranchHashId -> m (Map NameSegment (Map Referent NamespaceTermMappingId))
159+
getTermsAndConstructors :: forall m. (QueryA m e) => BranchHashId -> m (Map NameSegment (Map Referent NamespaceTermMappingId))
158160
getTermsAndConstructors branchHashId = do
159161
queryListRows @(NameSegment, Maybe Text, Maybe ComponentHash, Maybe PgComponentIndex, Maybe PgConstructorIndex, NamespaceTermMappingId)
160162
[sql| SELECT name_segment.text AS name_segment, builtin.text AS builtin_text, comp_hash.base32, COALESCE(term.component_index, constr_typ.component_index), constr.constructor_index, mapping.id
@@ -183,7 +185,7 @@ expectNamespace branchHashId = do
183185
)
184186
<&> Map.fromListWith (<>)
185187

186-
getTypes :: BranchHashId -> m (Map NameSegment (Map Reference NamespaceTypeMappingId))
188+
getTypes :: forall m. (QueryA m e) => BranchHashId -> m (Map NameSegment (Map Reference NamespaceTypeMappingId))
187189
getTypes branchHashId = do
188190
queryListRows
189191
[sql| SELECT name_segment.text AS name_segment, builtin.text AS builtin_text, component_hashes.base32, typ.component_index, mapping.id
@@ -207,7 +209,7 @@ expectNamespace branchHashId = do
207209
)
208210
<&> Map.fromListWith (<>)
209211

210-
getPatches :: BranchHashId -> m (Map NameSegment (PatchHash, m Patch))
212+
getPatches :: forall m. (QueryM m e) => BranchHashId -> m (Map NameSegment (PatchHash, m Patch))
211213
getPatches branchHashId = do
212214
queryListRows
213215
[sql| SELECT name_segment.text AS name_segment, patch.hash, patch.id
@@ -222,7 +224,7 @@ expectNamespace branchHashId = do
222224
)
223225
<&> Map.fromList
224226

225-
getChildren :: BranchHashId -> m (Map NameSegment (CausalBranch m))
227+
getChildren :: forall m. (QueryM m e) => BranchHashId -> m (Map NameSegment (CausalBranch m))
226228
getChildren branchHashId = do
227229
childIds <-
228230
queryListRows
@@ -235,7 +237,7 @@ expectNamespace branchHashId = do
235237
(name_segment,) <$> expectCausalNamespace causalId
236238
pure $ Map.fromList childList
237239

238-
loadTermMetadata :: NamespaceTermMappingId -> m MdValues
240+
loadTermMetadata :: forall m. (QueryA m e) => NamespaceTermMappingId -> m MdValues
239241
loadTermMetadata mappingId = do
240242
queryListRows @(Maybe Hash, Maybe PgComponentIndex, Maybe Text)
241243
[sql|
@@ -248,7 +250,7 @@ expectNamespace branchHashId = do
248250
|]
249251
<&> formatMdValues
250252

251-
loadTypeMetadata :: NamespaceTypeMappingId -> m MdValues
253+
loadTypeMetadata :: forall m. (QueryA m e) => NamespaceTypeMappingId -> m MdValues
252254
loadTypeMetadata mappingId =
253255
do
254256
queryListRows @(Maybe Hash, Maybe PgComponentIndex, Maybe Text)
@@ -608,7 +610,7 @@ savePgNamespace mayBh b@(BranchFull.Branch {terms, types, patches, children}) =
608610
execute_ [sql| SELECT save_namespace(#{bhId}) |]
609611

610612
-- | Hash a namespace into a BranchHash
611-
hashPgNamespace :: forall m. (QueryM m) => PgNamespace -> m BranchHash
613+
hashPgNamespace :: forall m e. (QueryM m e) => PgNamespace -> m BranchHash
612614
hashPgNamespace b = do
613615
BranchFull.Branch {terms, types, patches, children} <-
614616
b
@@ -660,7 +662,7 @@ hashPgNamespace b = do
660662
Referent.Ref r -> H.ReferentRef (v2ToH2Reference r)
661663
Referent.Con r cid -> H.ReferentCon (v2ToH2Reference r) cid
662664

663-
hashCausal :: (QueryM m) => BranchHashId -> Set CausalId -> m CausalHash
665+
hashCausal :: (QueryM m e) => BranchHashId -> Set CausalId -> m CausalHash
664666
hashCausal branchHashId ancestorIds = do
665667
branchHash <- HashQ.expectBranchHash branchHashId
666668
ancestors <-
@@ -778,7 +780,7 @@ saveV2BranchShallow v2Branch = do
778780
mdValuesToMetadataSetFormat (V2.MdValues meta) = BranchFull.Inline meta
779781

780782
-- | Get the namespace stats of a namespace.
781-
expectNamespaceStatsOf :: (QueryM m) => Traversal s t BranchHash NamespaceStats -> s -> m t
783+
expectNamespaceStatsOf :: (QueryM m e) => Traversal s t BranchHash NamespaceStats -> s -> m t
782784
expectNamespaceStatsOf trav s =
783785
s
784786
& unsafePartsOf trav %%~ \branchHashes -> do
@@ -867,13 +869,13 @@ importAccessibleCausals causalHashes = do
867869
-- Order by determines which values are returned by DISTINCT ON
868870
ORDER BY copyable.causal_id ASC, copyable.created_at DESC
869871
|]
870-
for_ results \case
872+
lift $ PG.pFor_ results \case
871873
(causalId, owner) -> do
872874
execute_ [sql| SELECT copy_causal_into_codebase(#{causalId}, #{owner}, #{codebaseOwnerUserId}) |]
873875
pure results
874876

875877
-- | Find the best common ancestor between two causals for diffs or merges.
876-
bestCommonAncestor :: (QueryM m) => CausalId -> CausalId -> m (Maybe CausalId)
878+
bestCommonAncestor :: (QueryM m e) => CausalId -> CausalId -> m (Maybe CausalId)
877879
bestCommonAncestor a b = do
878880
query1Col
879881
[sql| SELECT best_common_causal_ancestor(#{a}, #{b}) as causal_id

0 commit comments

Comments
 (0)