Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Experimental] Add SyncV2 protocol #5513

Draft
wants to merge 53 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
bf47a49
Add Hedgehog roundtrip tests for cbor encoding
ChrisPenner Aug 5, 2024
3228582
Fill in remaining instances for temp entity format
ChrisPenner Aug 5, 2024
53b1701
Implement CBOR decoder for TempEntities
ChrisPenner Aug 5, 2024
9785884
WIP syncv2 client
ChrisPenner Aug 6, 2024
bc42c13
Implement Serialise for Download Chunks
ChrisPenner Aug 6, 2024
f2b62de
SyncV2 WIP
ChrisPenner Aug 7, 2024
86754c1
Client is compiling
ChrisPenner Aug 12, 2024
3aee5e7
SyncV2 WIP
ChrisPenner Aug 12, 2024
b4d7ea8
Fix exports
ChrisPenner Aug 12, 2024
109248d
WIP
ChrisPenner Aug 12, 2024
dd5aee9
Fix use of withStream
ChrisPenner Aug 13, 2024
98a65c9
Switch from conduit to foreach
ChrisPenner Aug 13, 2024
01c41af
More experiments
ChrisPenner Aug 15, 2024
fb391fb
Write all entities in a single transaction, big boost!
ChrisPenner Aug 18, 2024
62ab29b
Unparallelize unpacking, but run in a single transaction.
ChrisPenner Aug 18, 2024
831f5da
Remove download callback
ChrisPenner Aug 18, 2024
941dc04
Add a buncha sqlite pragmas
ChrisPenner Aug 18, 2024
0c692b3
Add prepared statement cache.
ChrisPenner Aug 18, 2024
890905d
Allow nulls in temp_entity table
ChrisPenner Aug 15, 2024
b31473c
Remove temp_entity checking
ChrisPenner Aug 15, 2024
1b637b2
Smarter text and hash saving queries
ChrisPenner Aug 19, 2024
6cf6f4c
Skip dependency checking because we're in sorted order.
ChrisPenner Aug 19, 2024
fb12103
Merge branch 'trunk' into syncv2/experiments
ChrisPenner Dec 3, 2024
c32d0f4
Fix up merge
ChrisPenner Dec 3, 2024
6c435eb
Merge remote-tracking branch 'origin/trunk' into syncv2/experiments
ChrisPenner Dec 13, 2024
e5c175b
Update cabal
ChrisPenner Dec 13, 2024
a4f1bba
Merge branch 'cp/batched-diffs' into syncv2/experiments
ChrisPenner Dec 13, 2024
a3750a6
Handle initial chunks
ChrisPenner Dec 14, 2024
9cbc7d3
A bunch of sync refactors
ChrisPenner Dec 14, 2024
439360b
Port syncing code to use conduit instead
ChrisPenner Dec 16, 2024
e19038b
Better error handling
ChrisPenner Dec 16, 2024
f1e5851
Parallelize validation on unsorted stream
ChrisPenner Dec 17, 2024
4ca76ad
Add runTransactionExceptT
ChrisPenner Dec 17, 2024
7b96cda
Huge code cleanup
ChrisPenner Dec 17, 2024
503e501
Start code for syncing to file
ChrisPenner Dec 16, 2024
e4a7512
Add framing support for file decoder
ChrisPenner Dec 17, 2024
7e83617
Implement 'createSyncFile'
ChrisPenner Dec 17, 2024
8ab3f2d
Add sync.to-file command
ChrisPenner Dec 17, 2024
7fa3391
Topologically sort sync files
ChrisPenner Dec 17, 2024
290a953
Building with new sync.to-file command
ChrisPenner Dec 17, 2024
94755c8
Fix missing datain init header
ChrisPenner Dec 17, 2024
3203612
Clean up dep calculation
ChrisPenner Dec 18, 2024
f42c1b4
Rename sync helpers
ChrisPenner Dec 18, 2024
a9d9594
Wire in sync.from-file
ChrisPenner Dec 18, 2024
61393cc
Break resource handling, but get file sync kinda working.
ChrisPenner Dec 18, 2024
65dd42e
Write ErrGroupT Monad
ChrisPenner Dec 18, 2024
597ff68
BailT Monad stuff
ChrisPenner Dec 19, 2024
8edf4c1
Fix resourceT resource handling
ChrisPenner Dec 19, 2024
2c95433
Add gzip
ChrisPenner Dec 19, 2024
5d8e60e
Implement sync.from-codebase
ChrisPenner Dec 19, 2024
1f5ffa5
SyncV2 cleanup
ChrisPenner Dec 19, 2024
0433202
Remove unused temp-table changes
ChrisPenner Dec 19, 2024
7657cfc
Skip validation if syncing from Share Prod
ChrisPenner Dec 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dist-newstyle
*.hie
*.prof
*.prof.html
*.profiterole.*
*.hp
*.ps
/.direnv/
Expand Down
3 changes: 2 additions & 1 deletion codebase2/codebase-sqlite/U/Codebase/Sqlite/Branch/Format.hs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ data BranchLocalIds' t d p c = LocalIds
branchPatchLookup :: Vector p,
branchChildLookup :: Vector c
}
deriving (Show)
deriving (Show, Eq)

-- | Bytes encoding a LocalBranch
newtype LocalBranchBytes = LocalBranchBytes ByteString
Expand All @@ -110,6 +110,7 @@ newtype LocalBranchBytes = LocalBranchBytes ByteString
data SyncBranchFormat' parent text defn patch child
= SyncFull (BranchLocalIds' text defn patch child) LocalBranchBytes
| SyncDiff parent (BranchLocalIds' text defn patch child) LocalBranchBytes
deriving (Eq, Show)

type SyncBranchFormat = SyncBranchFormat' BranchObjectId TextId ObjectId PatchObjectId (BranchObjectId, CausalHashId)

Expand Down
1 change: 1 addition & 0 deletions codebase2/codebase-sqlite/U/Codebase/Sqlite/Causal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ data SyncCausalFormat' causalHash valueHash = SyncCausalFormat
{ valueHash :: valueHash,
parents :: Vector causalHash
}
deriving stock (Eq, Show)

type SyncCausalFormat = SyncCausalFormat' CausalHashId BranchHashId
2 changes: 2 additions & 0 deletions codebase2/codebase-sqlite/U/Codebase/Sqlite/Decl/Format.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ type SyncDeclFormat =

data SyncDeclFormat' t d
= SyncDecl (SyncLocallyIndexedComponent' t d)
deriving stock (Eq, Show)

newtype SyncLocallyIndexedComponent' t d
= SyncLocallyIndexedComponent (Vector (LocalIds' t d, ByteString))
deriving stock (Eq, Show)

-- [OldDecl] ==map==> [NewDecl] ==number==> [(NewDecl, Int)] ==sort==> [(NewDecl, Int)] ==> permutation is map snd of that

Expand Down
1 change: 1 addition & 0 deletions codebase2/codebase-sqlite/U/Codebase/Sqlite/Entity.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ data SyncEntity' text hash defn patch branchh branch causal
| N (Namespace.SyncBranchFormat' branch text defn patch (branch, causal))
| P (Patch.SyncPatchFormat' patch text hash defn)
| C (Causal.SyncCausalFormat' causal branchh)
deriving stock (Eq, Show)

entityType :: SyncEntity' text hash defn patch branchh branch causal -> TempEntityType
entityType = \case
Expand Down
2 changes: 1 addition & 1 deletion codebase2/codebase-sqlite/U/Codebase/Sqlite/LocalIds.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ data LocalIds' t h = LocalIds
{ textLookup :: Vector t,
defnLookup :: Vector h
}
deriving (Functor, Show)
deriving stock (Functor, Show, Eq)

type LocalIds = LocalIds' TextId ObjectId

Expand Down
2 changes: 2 additions & 0 deletions codebase2/codebase-sqlite/U/Codebase/Sqlite/Patch/Format.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ data PatchLocalIds' t h d = LocalIds
patchHashLookup :: Vector h,
patchDefnLookup :: Vector d
}
deriving stock (Eq, Show)

type SyncPatchFormat = SyncPatchFormat' PatchObjectId TextId HashId ObjectId

data SyncPatchFormat' parent text hash defn
= SyncFull (PatchLocalIds' text hash defn) ByteString
| -- | p is the identity of the thing that the diff is relative to
SyncDiff parent (PatchLocalIds' text hash defn) ByteString
deriving stock (Eq, Show)

-- | Apply a list of patch diffs to a patch, left to right.
applyPatchDiffs :: Patch -> [PatchDiff] -> Patch
Expand Down
92 changes: 60 additions & 32 deletions codebase2/codebase-sqlite/U/Codebase/Sqlite/Queries.hs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ module U.Codebase.Sqlite.Queries
expectEntity,
syncToTempEntity,
insertTempEntity,
insertTempEntityV2,
saveTempEntityInMain,
expectTempEntity,
deleteTempEntity,
Expand Down Expand Up @@ -315,6 +316,7 @@ import Data.Map.NonEmpty qualified as NEMap
import Data.Maybe qualified as Maybe
import Data.Sequence qualified as Seq
import Data.Set qualified as Set
import Data.Set.NonEmpty (NESet)
import Data.Text qualified as Text
import Data.Text.Encoding qualified as Text
import Data.Text.Lazy qualified as Text.Lazy
Expand Down Expand Up @@ -532,23 +534,18 @@ countWatches = queryOneCol [sql| SELECT COUNT(*) FROM watch |]

saveHash :: Hash32 -> Transaction HashId
saveHash hash = do
execute
[sql|
INSERT INTO hash (base32) VALUES (:hash)
ON CONFLICT DO NOTHING
|]
expectHashId hash
loadHashId hash >>= \case
Just h -> pure h
Nothing -> do
queryOneCol
[sql|
INSERT INTO hash (base32) VALUES (:hash)
RETURNING id
|]

saveHashes :: Traversable f => f Hash32 -> Transaction (f HashId)
saveHashes hashes = do
for_ hashes \hash ->
execute
[sql|
INSERT INTO hash (base32)
VALUES (:hash)
ON CONFLICT DO NOTHING
|]
traverse expectHashId hashes
for hashes saveHash

saveHashHash :: Hash -> Transaction HashId
saveHashHash = saveHash . Hash32.fromHash
Expand Down Expand Up @@ -623,13 +620,15 @@ expectBranchHashForCausalHash ch = do

saveText :: Text -> Transaction TextId
saveText t = do
execute
[sql|
INSERT INTO text (text)
VALUES (:t)
ON CONFLICT DO NOTHING
|]
expectTextId t
loadTextId t >>= \case
Just h -> pure h
Nothing -> do
queryOneCol
[sql|
INSERT INTO text (text)
VALUES (:t)
RETURNING id
|]

saveTexts :: Traversable f => f Text -> Transaction (f TextId)
saveTexts =
Expand Down Expand Up @@ -686,7 +685,7 @@ saveObject ::
ObjectType ->
ByteString ->
Transaction ObjectId
saveObject hh h t blob = do
saveObject _hh h t blob = do
execute
[sql|
INSERT INTO object (primary_hash_id, type_id, bytes)
Expand All @@ -697,9 +696,9 @@ saveObject hh h t blob = do
saveHashObject h oId 2 -- todo: remove this from here, and add it to other relevant places once there are v1 and v2 hashes
rowsModified >>= \case
0 -> pure ()
_ -> do
hash <- expectHash32 h
tryMoveTempEntityDependents hh hash
_ -> pure ()
-- hash <- expectHash32 h
-- tryMoveTempEntityDependents hh hash
pure oId

expectObject :: SqliteExceptionReason e => ObjectId -> (ByteString -> Either e a) -> Transaction a
Expand Down Expand Up @@ -957,7 +956,7 @@ saveCausal ::
BranchHashId ->
[CausalHashId] ->
Transaction ()
saveCausal hh self value parents = do
saveCausal _hh self value parents = do
execute
[sql|
INSERT INTO causal (self_hash_id, value_hash_id)
Expand All @@ -973,27 +972,27 @@ saveCausal hh self value parents = do
INSERT INTO causal_parent (causal_id, parent_id)
VALUES (:self, :parent)
|]
flushCausalDependents hh self
-- flushCausalDependents hh self

flushCausalDependents ::
_flushCausalDependents ::
HashHandle ->
CausalHashId ->
Transaction ()
flushCausalDependents hh chId = do
_flushCausalDependents hh chId = do
hash <- expectHash32 (unCausalHashId chId)
tryMoveTempEntityDependents hh hash
_tryMoveTempEntityDependents hh hash

-- | `tryMoveTempEntityDependents #foo` does this:
-- 0. Precondition: We just inserted object #foo.
-- 1. Look up the dependents of #foo
-- 2. Delete #foo as dependency from temp_entity_missing_dependency. e.g. (#bar, #foo), (#baz, #foo)
-- 3. For each like #bar and #baz with no more rows in temp_entity_missing_dependency,
-- insert_entity them.
tryMoveTempEntityDependents ::
_tryMoveTempEntityDependents ::
HashHandle ->
Hash32 ->
Transaction ()
tryMoveTempEntityDependents hh dependency = do
_tryMoveTempEntityDependents hh dependency = do
dependents <-
queryListCol
[sql|
Expand Down Expand Up @@ -2993,6 +2992,35 @@ insertTempEntity entityHash entity missingDependencies = do
entityType =
Entity.entityType entity

-- | Insert a new `temp_entity` row, and its associated 1+ `temp_entity_missing_dependency` rows.
--
-- Preconditions:
-- 1. The entity does not already exist in "main" storage (`object` / `causal`)
-- 2. The entity does not already exist in `temp_entity`.
insertTempEntityV2 :: Hash32 -> TempEntity -> NESet Hash32 -> Transaction ()
insertTempEntityV2 entityHash entity missingDependencies = do
execute
[sql|
INSERT INTO temp_entity (hash, blob, type_id)
VALUES (:entityHash, :entityBlob, :entityType)
ON CONFLICT DO NOTHING
|]

for_ missingDependencies \depHash ->
execute
[sql|
INSERT INTO temp_entity_missing_dependency (dependent, dependency)
VALUES (:entityHash, :depHash)
|]
where
entityBlob :: ByteString
entityBlob =
runPutS (Serialization.putTempEntity entity)

entityType :: TempEntityType
entityType =
Entity.entityType entity

-- | Delete a row from the `temp_entity` table, if it exists.
deleteTempEntity :: Hash32 -> Transaction ()
deleteTempEntity hash =
Expand Down
2 changes: 2 additions & 0 deletions codebase2/codebase-sqlite/U/Codebase/Sqlite/Term/Format.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ newtype LocallyIndexedComponent' t d = LocallyIndexedComponent

newtype SyncLocallyIndexedComponent' t d
= SyncLocallyIndexedComponent (Vector (LocalIds' t d, ByteString))
deriving stock (Eq, Show)

{-
message = "hello, world" -> ABT { ... { Term.F.Text "hello, world" } } -> hashes to (#abc, 0)
Expand Down Expand Up @@ -127,6 +128,7 @@ data TermFormat' t d = Term (LocallyIndexedComponent' t d)
type SyncTermFormat = SyncTermFormat' TextId ObjectId

data SyncTermFormat' t d = SyncTerm (SyncLocallyIndexedComponent' t d)
deriving stock (Eq, Show)

data WatchResultFormat
= WatchResult WatchLocalIds Term
Expand Down
3 changes: 2 additions & 1 deletion codebase2/codebase-sqlite/sql/001-temp-entity-tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ create table if not exists temp_entity (
create table if not exists temp_entity_missing_dependency (
dependent text not null references temp_entity(hash),
dependency text not null,
dependencyJwt text not null,
-- TODO: this is just for testing
dependencyJwt text null,
unique (dependent, dependency)
);
create index if not exists temp_entity_missing_dependency_ix_dependent on temp_entity_missing_dependency (dependent);
Expand Down
2 changes: 1 addition & 1 deletion codebase2/codebase-sqlite/unison-codebase-sqlite.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 1.12

-- This file has been generated from package.yaml by hpack version 0.36.0.
-- This file has been generated from package.yaml by hpack version 0.37.0.
--
-- see: https://github.com/sol/hpack

Expand Down
3 changes: 3 additions & 0 deletions hie.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ cradle:
- path: "unison-share-api/src"
component: "unison-share-api:lib"

- path: "unison-share-api/tests"
component: "unison-share-api:test:unison-share-api-tests"

- path: "unison-share-projects-api/src"
component: "unison-share-projects-api:lib"

Expand Down
5 changes: 2 additions & 3 deletions lib/unison-pretty-printer/src/Unison/Util/AnnotatedText.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import Unison.Util.Monoid (intercalateMap)
import Unison.Util.Range (Range (..), inRange)

data Segment a = Segment {segment :: String, annotation :: Maybe a}
deriving (Eq, Show, Functor, Foldable, Generic)
deriving (Eq, Show, Ord, Functor, Foldable, Generic)

toPair :: Segment a -> (String, Maybe a)
toPair (Segment s a) = (s, a)

newtype AnnotatedText a = AnnotatedText (Seq (Segment a))
deriving (Eq, Functor, Foldable, Show, Generic)
deriving (Eq, Functor, Foldable, Show, Ord, Generic)

instance Semigroup (AnnotatedText a) where
AnnotatedText (as :|> Segment "" _) <> bs = AnnotatedText as <> bs
Expand Down Expand Up @@ -204,7 +204,6 @@ snipWithContext margin source =
-- if all annotations so far can be joined without .. separations
if null rest
then -- if this one can be joined to the new region without .. separation

if withinMargin r0 r1
then -- add it to the first set and grow the compare region
(Just $ r0 <> r1, Map.insert r1 a1 taken, mempty)
Expand Down
1 change: 1 addition & 0 deletions lib/unison-sqlite/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ library:

dependencies:
- base
- containers
- direct-sqlite
- megaparsec
- pretty-simple
Expand Down
1 change: 1 addition & 0 deletions lib/unison-sqlite/src/Unison/Sqlite.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module Unison.Sqlite
Transaction,
runTransaction,
runTransactionWithRollback,
runTransactionExceptT,
runReadOnlyTransaction,
runWriteTransaction,
cacheTransaction,
Expand Down
Loading
Loading