Skip to content

Commit

Permalink
Changed recompute on demand
Browse files Browse the repository at this point in the history
  • Loading branch information
csansoon committed Jul 23, 2024
1 parent 6ebae08 commit 67e2613
Show file tree
Hide file tree
Showing 12 changed files with 337 additions and 221 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('getDocumentsAtCommit', () => {
const documents = result.unwrap()

expect(documents.length).toBe(1)
expect(documents[0]!.id).toBe(doc.id)
expect(documents[0]!.documentUuid).toBe(doc.documentUuid)
})

it('returns the right document version for each commit', async (ctx) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Result,
TypedResult,
} from '@latitude-data/core'
import { LatitudeError } from '$core/lib/errors'
import { LatitudeError, NotFoundError } from '$core/lib/errors'
import { and, eq, getTableColumns, isNotNull, lte, max } from 'drizzle-orm'

async function fetchDocumentsFromMergedCommits(
Expand Down Expand Up @@ -79,14 +79,17 @@ export async function getDocumentsAtCommit(
{ commitId }: { commitId: number },
tx = database,
): Promise<TypedResult<DocumentVersion[], LatitudeError>> {
const commitResult = await findCommitById({ id: commitId })
const commitResult = await findCommitById({ id: commitId }, tx)
if (commitResult.error) return commitResult
const commit = commitResult.value!

const documentsFromMergedCommits = await fetchDocumentsFromMergedCommits({
projectId: commit.projectId,
maxMergedAt: commit.mergedAt,
})
const documentsFromMergedCommits = await fetchDocumentsFromMergedCommits(
{
projectId: commit.projectId,
maxMergedAt: commit.mergedAt,
},
tx,
)

if (commit.mergedAt !== null) {
// Referenced commit is merged. No additional documents to return.
Expand Down Expand Up @@ -130,7 +133,7 @@ export async function getDocumentAtCommit(
(d) => d.documentUuid === documentUuid,
)

if (!document) return Result.error(new LatitudeError('Document not found'))
if (!document) return Result.error(new NotFoundError('Document not found'))

return Result.ok(document)
}
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/services/commits/merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
Commit,
commits,
database,
recomputeChanges,
Result,
Transaction,
} from '@latitude-data/core'
Expand Down Expand Up @@ -35,6 +36,16 @@ export async function mergeCommit(
)
}

const recomputedResults = await recomputeChanges({ commitId }, tx)
if (recomputedResults.error) return recomputedResults
if (Object.keys(recomputedResults.value.errors).length > 0) {
return Result.error(
new LatitudeError(
'There are errors in the updated documents in this commit',
),
)
}

const result = await tx
.update(commits)
.set({ mergedAt })
Expand Down
28 changes: 9 additions & 19 deletions packages/core/src/services/documents/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,30 +54,20 @@ describe('createNewDocument', () => {
})

expect(result.ok).toBe(false)
expect(result.error!.message).toBe(
'Cannot create a document version in a merged commit',
)
expect(result.error!.message).toBe('Cannot modify a merged commit')
})

it('modifies other documents if it is referenced by another document', async (ctx) => {
const { project } = await ctx.factories.createProject({
documents: {
main: '<ref prompt="referenced/doc" />',
},
})

it('fails when trying to create a document in a merged commit', async (ctx) => {
const { project } = await ctx.factories.createProject()
const { commit } = await ctx.factories.createDraft({ project })
await createNewDocument({
await mergeCommit({ commitId: commit.id })

const result = await createNewDocument({
commitId: commit.id,
path: 'referenced/doc',
path: 'foo',
})

const changes = await listCommitChanges({ commitId: commit.id }).then((r) =>
r.unwrap(),
)
expect(changes.length).toBe(2)
const changedDocsPahts = changes.map((c) => c.path)
expect(changedDocsPahts).toContain('main')
expect(changedDocsPahts).toContain('referenced/doc')
expect(result.ok).toBe(false)
expect(result.error!.message).toBe('Cannot modify a merged commit')
})
})
57 changes: 21 additions & 36 deletions packages/core/src/services/documents/create.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,39 @@
import { DocumentVersion, Result } from '@latitude-data/core'
import { findCommitById, getDocumentsAtCommit } from '$core/data-access'
import { Result, Transaction, TypedResult } from '$core/lib'
import { BadRequestError } from '$core/lib/errors'

import {
getDraft,
getMergedAndDraftDocuments,
replaceCommitChanges,
resolveDocumentChanges,
} from './shared'
import { DocumentVersion, documentVersions } from '$core/schema'

export async function createNewDocument({
commitId,
path,
content,
}: {
commitId: number
path: string
}) {
try {
const draft = (await getDraft(commitId)).unwrap()

const [mergedDocuments, draftDocuments] = (
await getMergedAndDraftDocuments({
draft,
})
).unwrap()
content?: string
}): Promise<TypedResult<DocumentVersion, Error>> {
return await Transaction.call(async (tx) => {
const commit = (await findCommitById({ id: commitId }, tx)).unwrap()
if (commit.mergedAt !== null) {
return Result.error(new BadRequestError('Cannot modify a merged commit'))
}

if (path && draftDocuments.find((d) => d.path === path)) {
const currentDocs = (await getDocumentsAtCommit({ commitId }, tx)).unwrap()
if (currentDocs.find((d) => d.path === path)) {
return Result.error(
new BadRequestError('A document with the same path already exists'),
)
}

draftDocuments.push({
path,
content: '',
} as DocumentVersion)

const documentsToUpdate = await resolveDocumentChanges({
originalDocuments: mergedDocuments,
newDocuments: draftDocuments,
})

const newDraftDocuments = (
await replaceCommitChanges({
const newDoc = await tx
.insert(documentVersions)
.values({
commitId,
documentChanges: documentsToUpdate,
path,
content: content ?? '',
})
).unwrap()
.returning()

return Result.ok(newDraftDocuments.find((d) => d.path === path)!)
} catch (error) {
return Result.error(error as Error)
}
return Result.ok(newDoc[0]!)
})
}
1 change: 1 addition & 0 deletions packages/core/src/services/documents/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './create'
export * from './update'
export * from './recomputeChanges'
64 changes: 64 additions & 0 deletions packages/core/src/services/documents/recomputeChanges.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { CompileError } from '@latitude-data/compiler'
import { database } from '$core/client'
import { findCommitById } from '$core/data-access'
import { Result, TypedResult } from '$core/lib'
import { BadRequestError } from '$core/lib/errors'
import { DocumentVersion } from '$core/schema'

import {
getMergedAndDraftDocuments,
replaceCommitChanges,
resolveDocumentChanges,
} from './utils'

type RecomputedChanges = {
documents: DocumentVersion[]
errors: { [documentUuid: string]: CompileError[] }
}

export async function recomputeChanges(
{
commitId,
}: {
commitId: number
},
tx = database,
): Promise<TypedResult<RecomputedChanges, Error>> {
try {
const draft = (await findCommitById({ id: commitId }, tx)).unwrap()
if (draft.mergedAt !== null) {
return Result.error(
new BadRequestError('Cannot recompute changes in a merged commit'),
)
}

const [mergedDocuments, draftDocuments] = (
await getMergedAndDraftDocuments(
{
draft,
},
tx,
)
).unwrap()

const { documents: documentsToUpdate, errors } =
await resolveDocumentChanges({
originalDocuments: mergedDocuments,
newDocuments: draftDocuments,
})

const newDraftDocuments = (
await replaceCommitChanges(
{
commitId,
documentChanges: documentsToUpdate,
},
tx,
)
).unwrap()

return Result.ok({ documents: newDraftDocuments, errors })
} catch (error) {
return Result.error(error as Error)
}
}
Loading

0 comments on commit 67e2613

Please sign in to comment.