Skip to content

Commit

Permalink
Fixed: “transaction not found.”
Browse files Browse the repository at this point in the history
  • Loading branch information
heymartinadams committed Nov 1, 2022
1 parent 0e6e8cc commit 734f9ed
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 122 deletions.
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -23,7 +23,7 @@
"dependencies": {
"@clerk/clerk-js": "^4.11.0",
"@clerk/nextjs": "^4.5.4",
"@prisma/client": "4.6.0-dev.32",
"@prisma/client": "4.6.0-dev.43",
"nanoid": "^3.3.4",
"next": "^12.3.1",
"pusher": "^5.1.1-beta",
Expand All @@ -34,7 +34,7 @@
"replicache-react": "^2.10.0"
},
"devDependencies": {
"prisma": "4.6.0-dev.32"
"prisma": "4.6.0-dev.43"
},
"prettier": {
"arrowParens": "avoid",
Expand Down
79 changes: 31 additions & 48 deletions pages/api/replicache/pull.js
Expand Up @@ -16,56 +16,39 @@ const PagesApiReplicachePull = async (req, res) => {

if (!clientID || !spaceId || cookie === undefined) return res.status(403)

try {
await prisma.$transaction(
async tx => {
// #1. Get last mutation Id for the current client
let { data: lastMutationId } = await utilApiLastMutationIdGet({ clientID, tx })

// #2. Get all transactions done after the last client request for the current space
const { data: apiEntriesTodoGet } = await utilApiEntriesTodoGet({
cookie,
spaceId,
tx,
userId: user.id
})

// #3. Get the highest authoritative version number
const replicacheVersion = apiEntriesTodoGet?.length
? Math.max(...apiEntriesTodoGet?.map(x => x.lastModifiedVersion))
: 0

// #4. Put together a patch with instructions for the client
const patch = []

if (cookie === null) patch.push({ op: 'clear' })

patch.push(
...apiEntriesTodoGet?.map(todo => ({
op: !todo.isDeleted ? 'put' : 'del',
key: `todo/${todo.todoId}`,
value: { ...todo }
}))
)

// #5. Return object to client
res.json({ lastMutationID: lastMutationId, cookie: replicacheVersion, patch })

return true
},
// FIX: interactive transactions error still occurs with long wait times
{
maxWait: 20000,
timeout: 60000
}
await prisma.$transaction(async tx => {
// #1. Get last mutation Id for the current client
let { data: lastMutationId } = await utilApiLastMutationIdGet({ clientID, tx })

// #2. Get all transactions done after the last client request for the current space
const { data: apiEntriesTodoGet } = await utilApiEntriesTodoGet({
cookie,
spaceId,
tx,
userId: user.id
})

// #3. Get the highest authoritative version number
const replicacheVersion = apiEntriesTodoGet?.length
? Math.max(...apiEntriesTodoGet?.map(x => x.lastModifiedVersion))
: 0

// #4. Put together a patch with instructions for the client
const patch = []

if (cookie === null) patch.push({ op: 'clear' })

patch.push(
...apiEntriesTodoGet?.map(todo => ({
op: !todo.isDeleted ? 'put' : 'del',
key: `todo/${todo.todoId}`,
value: { ...todo }
}))
)
} catch (err) {
console.error(err)

res.status(500).send(err.toString())
} finally {
await prisma.$disconnect()
}
// #5. Return object to client
res.json({ lastMutationID: lastMutationId, cookie: replicacheVersion, patch })
})
}

export default PagesApiReplicachePull
81 changes: 32 additions & 49 deletions pages/api/replicache/push.js
Expand Up @@ -20,55 +20,38 @@ const PagesApiReplicachePush = async (req, res) => {

if (!clientID || !spaceId || !mutations) return res.status(403)

try {
await prisma.$transaction(
async tx => {
// #1. Get next `version` for space
const { data: versionNext, error: versionNextErr } = await utilApiVersionGetNext({
tx,
spaceId,
userId: user.id
})

if (versionNextErr) throw new Error('unauthorized')

// #2. Get last mutation Id for client
let { data: lastMutationId } = await utilApiLastMutationIdGet({ clientID, tx })

// #3. Iterate mutations, increase mutation Id on each iteration
const { data: nextMutationId } = await utilApiMutations({
lastMutationId,
mutations,
spaceId,
tx
})

// #4. Save mutation Id to Client
await utilApiLastMutationIdSave({ clientID, nextMutationId, tx })

// #5. Save new version to Space
await utilApiVersionSave({ tx, spaceId, version: versionNext })

return true
},
// FIX: interactive transactions error still occurs with long wait times
{
maxWait: 20000,
timeout: 60000
}
)

// #6. Poke client(s) to send a pull.
await utilApiPokeSend()

res.json({ done: true })
} catch (err) {
console.error(err)

res.status(500).send(err.toString())
} finally {
await prisma.$disconnect()
}
await prisma.$transaction(async tx => {
// #1. Get next `version` for space
const { data: versionNext, error: versionNextErr } = await utilApiVersionGetNext({
tx,
spaceId,
userId: user.id
})

// #2. Get last mutation Id for client
let { data: lastMutationId } = await utilApiLastMutationIdGet({ clientID, tx })

// #3. Iterate mutations, increase mutation Id on each iteration
const { data: nextMutationId } = await utilApiMutations({
lastMutationId,
mutations,
spaceId,
tx
})

// #4. Save mutation Id to Client
await utilApiLastMutationIdSave({ clientID, nextMutationId, tx })

// #5. Save new version to Space
await utilApiVersionSave({ tx, spaceId, version: versionNext })

return true
})

// #6. Poke client(s) to send a pull.
// await utilApiPokeSend()

res.json({ done: true })
}

export default PagesApiReplicachePush
20 changes: 17 additions & 3 deletions utils/api/versionGetNext.js
@@ -1,13 +1,27 @@
const UtilsApiVersionGet = async ({ tx, spaceId, userId }) => {
// Important: we need to make sure that the `spaceId` provided in the query is also owned by user
const prismaReplicacheSpaceFindFirst = await tx.space.findFirst({
const prismaSpaceFindFirst = await tx.space.findFirst({
where: { AND: [{ spaceId }, { userId }] },
select: { version: true }
})

if (!prismaReplicacheSpaceFindFirst) return { error: `spaceId #${spaceId} not found` }
if (prismaSpaceFindFirst?.version === undefined) {
const prismaSpaceCreateOne = await tx.space.create({
data: {
// --- PUBLIC ID ---
spaceId,
// --- RELATIONS ---
User: { connect: { userId } },
// --- FIELDS ---
version: 0
},
select: { version: true }
})

return { data: prismaReplicacheSpaceFindFirst.version + 1 }
return { data: prismaSpaceCreateOne.version + 1 }
}

return { data: prismaSpaceFindFirst.version + 1 }
}

export default UtilsApiVersionGet
2 changes: 0 additions & 2 deletions utils/auth.js
@@ -1,7 +1,5 @@
// Packages
import { withAuth, users } from '@clerk/nextjs/api'
// Utilities
import prisma from 'utils/prisma'

const UtilsAuth = withAuth(async (req, _) => {
const { sessionId, userId } = req.auth
Expand Down
36 changes: 18 additions & 18 deletions yarn.lock
Expand Up @@ -390,22 +390,22 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45"
integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==

"@prisma/client@4.6.0-dev.32":
version "4.6.0-dev.32"
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.6.0-dev.32.tgz#d6281def59e136bf9df93f5bd6b16a1bfa618006"
integrity sha512-tPjt5SAd6tDV5i6go7h35TyYadvhGkDOI3FyCe36cVpDkKYovH9zwrqu+sdOi3vc/oU3T4qZbo70OCAHd3OgHg==
"@prisma/client@4.6.0-dev.43":
version "4.6.0-dev.43"
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.6.0-dev.43.tgz#5776046ffe6f8354801d7eb68565ef422fe90dbd"
integrity sha512-kWwrYvvaZNn5tPaKwHi8NqiP+xLHl1Oe8kCImBnXR+0Lm2CeAgLDBkD6KMRLPq5y3WzkNJTufYMcWQjdjigpRA==
dependencies:
"@prisma/engines-version" "4.6.0-25.82339fb24e11ed3d770e6857c01d178293cc8eef"
"@prisma/engines-version" "4.6.0-43.69861a827f36ef2cd9436ce42d87399a304d67c3"

"@prisma/engines-version@4.6.0-25.82339fb24e11ed3d770e6857c01d178293cc8eef":
version "4.6.0-25.82339fb24e11ed3d770e6857c01d178293cc8eef"
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-4.6.0-25.82339fb24e11ed3d770e6857c01d178293cc8eef.tgz#6315855b859da1e7abb45a280c6c54a8aaddbc49"
integrity sha512-/9/ZSAgBcZNWtMhRK+ERHmp4RBbV1A/undirgJ5Fy4rLOeAGUDesfLfP/9JNsEi/P85j21UW7CfWZQvib1cE3w==
"@prisma/engines-version@4.6.0-43.69861a827f36ef2cd9436ce42d87399a304d67c3":
version "4.6.0-43.69861a827f36ef2cd9436ce42d87399a304d67c3"
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-4.6.0-43.69861a827f36ef2cd9436ce42d87399a304d67c3.tgz#65c5739bb4b920fbc1143e0b892e3278fe536e28"
integrity sha512-ebULn/9KpG09MTpclZj0dNtlKF4apByVa/aGs/DtnqXQAlXt15kebaI3hVGyj6D0nStSD1PubBS+Nr22hHO20g==

"@prisma/engines@4.6.0-dev.32":
version "4.6.0-dev.32"
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.6.0-dev.32.tgz#2d4c8815f8932a36bcf80b6aad12883b802629bb"
integrity sha512-GZbU+1n+Q+QmUNuMIF0OoPKkTqrGVPGmUS3c0IBi/BnME49Qoi7xrmOoDgEBsSj8HqSjfhYHfyphcnWB/GdfYQ==
"@prisma/engines@4.6.0-dev.43":
version "4.6.0-dev.43"
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.6.0-dev.43.tgz#27035796573844b3ca0e93b09fafd03498c53cc2"
integrity sha512-fTv1+rru1Vib+PRlRbA8qapR4e7kwosiNvHoZw2wPYy+dr/WFJsfn80V62/ns9jrWxuwKJaWZpP3Xa4DAhYjRQ==

"@swc/helpers@0.4.11":
version "0.4.11"
Expand Down Expand Up @@ -1112,12 +1112,12 @@ postcss@8.4.14:
picocolors "^1.0.0"
source-map-js "^1.0.2"

prisma@4.6.0-dev.32:
version "4.6.0-dev.32"
resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.6.0-dev.32.tgz#a738a76295fedb4923090c1e72a9513b8ca39636"
integrity sha512-E15wPYbj9gGMoeCubrpog0RnANbsyS1rlq/gU2PWk0fkix5fMNcfcqViUJwRF0A4xOQ+cUthRcYCXr749+mTTw==
prisma@4.6.0-dev.43:
version "4.6.0-dev.43"
resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.6.0-dev.43.tgz#a23d995b01388348cc9d82e072417012b20408c6"
integrity sha512-au39CsndOHGaQ0wOjw9ADMEsz9akn9kTxj3eXKB9E79qj89XOjYHPxDzg3NBAOO3P3EySNnt4droymkzgCXokQ==
dependencies:
"@prisma/engines" "4.6.0-dev.32"
"@prisma/engines" "4.6.0-dev.43"

pseudomap@^1.0.1:
version "1.0.2"
Expand Down

0 comments on commit 734f9ed

Please sign in to comment.