|
@@ -1,3 +1,4 @@
|
|
|
|
+import type { ClientSession } from 'mongodb'
|
|
import type { Context } from '../types'
|
|
import type { Context } from '../types'
|
|
import { ObjectId } from 'mongodb'
|
|
import { ObjectId } from 'mongodb'
|
|
import type { Task, TaskCreate, TaskUpdate } from './types'
|
|
import type { Task, TaskCreate, TaskUpdate } from './types'
|
|
@@ -44,14 +45,12 @@ async function createTaskModel(ctx: Context) {
|
|
* Move a task.
|
|
* Move a task.
|
|
* This function updates the position of all subsequent tasks and returns the total number of tasks affected.
|
|
* This function updates the position of all subsequent tasks and returns the total number of tasks affected.
|
|
*/
|
|
*/
|
|
- async function move(id: ObjectId | string, position: number) {
|
|
|
|
- if (ctx.config.mongo.useTransactions) return moveTx(id, position)
|
|
|
|
-
|
|
|
|
|
|
+ async function move(id: ObjectId | string, position: number, session?: ClientSession) {
|
|
// Update specified task
|
|
// Update specified task
|
|
const task = await collection.findOneAndUpdate(
|
|
const task = await collection.findOneAndUpdate(
|
|
{ _id: new ObjectId(id) },
|
|
{ _id: new ObjectId(id) },
|
|
{ $set: { position } },
|
|
{ $set: { position } },
|
|
- { returnDocument: 'after' },
|
|
|
|
|
|
+ { returnDocument: 'after', session },
|
|
)
|
|
)
|
|
// Not expected to happen, but type-safe
|
|
// Not expected to happen, but type-safe
|
|
if (!task) throw new Error('failed to get updated task')
|
|
if (!task) throw new Error('failed to get updated task')
|
|
@@ -61,8 +60,7 @@ async function createTaskModel(ctx: Context) {
|
|
_herd: task._herd,
|
|
_herd: task._herd,
|
|
_id: { $ne: new ObjectId(id) },
|
|
_id: { $ne: new ObjectId(id) },
|
|
position: { $gte: position },
|
|
position: { $gte: position },
|
|
-
|
|
|
|
- }).sort('position', 1)
|
|
|
|
|
|
+ }, { session }).sort('position', 1)
|
|
|
|
|
|
// Update subsequent tasks
|
|
// Update subsequent tasks
|
|
let affectedCount = 1
|
|
let affectedCount = 1
|
|
@@ -70,6 +68,7 @@ async function createTaskModel(ctx: Context) {
|
|
await collection.updateOne(
|
|
await collection.updateOne(
|
|
{ _id: task._id },
|
|
{ _id: task._id },
|
|
{ $set: { position: position + affectedCount } },
|
|
{ $set: { position: position + affectedCount } },
|
|
|
|
+ { session },
|
|
)
|
|
)
|
|
affectedCount++
|
|
affectedCount++
|
|
}
|
|
}
|
|
@@ -77,50 +76,6 @@ async function createTaskModel(ctx: Context) {
|
|
return { task, affectedCount }
|
|
return { task, affectedCount }
|
|
}
|
|
}
|
|
|
|
|
|
- /** Move a task using a transaction. */
|
|
|
|
- async function moveTx(id: ObjectId | string, position: number) {
|
|
|
|
- const session = ctx.mongo.startSession()
|
|
|
|
- try {
|
|
|
|
- session.startTransaction()
|
|
|
|
-
|
|
|
|
- // Update specified task
|
|
|
|
- const task = await collection.findOneAndUpdate(
|
|
|
|
- { _id: new ObjectId(id) },
|
|
|
|
- { $set: { position } },
|
|
|
|
- { returnDocument: 'after', session },
|
|
|
|
- )
|
|
|
|
- // Not expected to happen, but type-safe
|
|
|
|
- if (!task) throw new Error('failed to get updated task')
|
|
|
|
-
|
|
|
|
- // Get subsequent tasks
|
|
|
|
- const nextTasks = collection.find({
|
|
|
|
- _herd: task._herd,
|
|
|
|
- _id: { $ne: new ObjectId(id) },
|
|
|
|
- position: { $gte: position },
|
|
|
|
- }, { session }).sort('position', 1)
|
|
|
|
-
|
|
|
|
- // Update subsequent tasks
|
|
|
|
- let affectedCount = 1
|
|
|
|
- for await (const task of nextTasks) {
|
|
|
|
- await collection.updateOne(
|
|
|
|
- { _id: task._id },
|
|
|
|
- { $set: { position: position + affectedCount } },
|
|
|
|
- { session },
|
|
|
|
- )
|
|
|
|
- affectedCount++
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Commit and return
|
|
|
|
- await session.commitTransaction()
|
|
|
|
- return { task, affectedCount }
|
|
|
|
- } catch (err) {
|
|
|
|
- await session.abortTransaction()
|
|
|
|
- throw err
|
|
|
|
- } finally {
|
|
|
|
- await session.endSession()
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* Update a task.
|
|
* Update a task.
|
|
*/
|
|
*/
|