2017-01-18 25 views
1

Я относительно новичок в node.js, postgresql, обещаниях и потоках stackoverflow, поэтому извиняюсь заранее, если что-то звучит немного несвязано!обмен транзакцией или объектом задачи между несколькими запросами на нескольких контроллерах в pg-prom

В настоящее время я пытаюсь запустить несколько запросов в рамках цепочек, распределенных между различными контроллерами. Я хочу запустить все запросы в рамках одной транзакции или задачи, чтобы устранить несколько подключений и отключений в базе данных.

Я пробовал следующее, где я добавляю ученика и назначаю двух наставников для этого ученика. HTTP-запрос направляется к контроллеру ученика, который добавляет ученика через репозиторий учеников. Хранилище студент, где задача начинается и возвращается к контроллеру, который направляет его на контроллер наставника и по цепочке он идет ...

@ HttpPost("/api/students/create") 
addStudent(@ Req()request) { 

var studentid; 
var mentorids= []; 
//Add the student 
return this.studentRepository.addStudent(request.body.student) 
.then(newStudentId => { 
    studentid = newStudentId; 

    //Add the mentors, passing the transaction object received back from 
     studentRepository 

    return this.mentorController.addMentor(request.body.schoolid, request.body.mentors, newStudentId.transaction) 
    .then(result => { 
     var data = []; 
     console.log(result); 
     for (var role in result) { 
      data.push({ 
       mentorid: result[role].roleid, 
       studentid: studentid 
      }); 
     } 
     //Assigns the student to mentors in the link table 
     return this.studentRepository.assignMentor(data) 
     .then(result => { 
      return result; 
     }) 

    }) 

}); 

} 

Студент хранилище

addStudent(student): any { 
return this.collection.task(t => { 
    return this.collection.one(this.sql.addStudent, student) 
    .then(studentid => { 
     return { 
      studentid: studentid.studentid, 
      transaction: t 
     } 
    }); 

}) 
} 

контроллер Mentor

addMentor(institutionid: number, mentors, t): any { 

var promises = []; 
var mentorIds = []; 
for (var role in mentors) { 
    promises.push(this.roleController.registerRole(institutionid,mentors[role].role,t)); 
} 
return t.batch(promises) 
.then(result => { 
    return Promise.resolve(result); 
}) 

} 

контроллер Роль

@ HttpPost("/api/roles/register") 
registerRole(institutionid, @ Req()request, t ?) : any { 
console.log(request); 
return this.roleRepository.checkRoleEnrollment(institutionid, request.email, request.roletype, t) 
.then(result => { 
    return this.roleRepository.addRoleEnrollment(institutionid, request, t) 
    .then(data => { 
     return this.roleRepository.updateRoleEnrollment(data.roleenrollmentid, data.roleid) 
     .then(d => { 
      return data; 
     }) 

    }) 
}) 
.catch (error => { 
    return Promise.reject(error); 
}); 
} 

Я получаю следующее сообщение об ошибке, когда я звоню checkEnrollment в контроллере Роль:

"name": "Error", 
"message": "Unexpected call outside of task.", 
"stack": "Error: Unexpected call outside of task. at Task.query 
(\api\node_modules\pg-promise\lib\task.js:118:19) 
at Task.obj.oneOrNone (\api\node_modules\pg-promise\lib\database.js:491:31)   
at RoleRepository.checkRoleEnrollment.... 

Любая помощь будет оценена. Заранее благодарю.

+0

Эта ошибка означает, что вы пытаетесь получить доступ к соединению 't', выделенному задачей где-то вне функции обратного вызова задачи, то есть обратный вызов задачи вернулся, соединение было выпущено, а затем вы используете объект соединения, выделенный задача от somwhere else, которая, конечно, недействительна. –

ответ

2

В соответствии с моим предыдущим комментарием:

Эта ошибка означает, что вы пытаетесь получить доступ соединение t выделенную задачу где-то за пределами функции обратного вызова по задаче, т.е. обратного выполнения задачи вернулся, связь была выпущена, а затем вы используете объект соединения, выделенный этой задачей из другого места, что, конечно, недействительно.

b.t.w. Я автор pg-promise;)

Ниже то, что ваш код эффективно делать, в упрощенной форме:

var cnReference; 

db.task(t => { 
    cnReference = t; 

    // can only use `t` connection while executing the callback 
}) 
    .then(data => { 
     // we are now outside of the task; 
     // the task's connection has been closed already, 
     // and we can do nothing with it anymore! 
     return cnReference.query('SELECT...'); 
    }) 
    .catch(error => { 
     // ERROR: Unexpected call outside of task. 

     // We cannot use a task connection object outside of the task's callback! 
    }); 

Вы должны исправить выполнение, чтобы убедиться, что это не произойдет.

+1

Спасибо. Это произошло со мной, поскольку я ранее управлял, чтобы получить транзакцию, но все запросы были в том же хранилище для этого. Я могу заставить задачу работать с разными контроллерами и репозиториями, но в настоящее время запускает задачу в контроллере, в отличие от первого вызванного репозитория. – Faz

+0

@Faz, если вы следуете шаблону многократного использования, как показано в [pg-prom-demo] (https://github.com/vitaly-t/pg-promise-demo), тогда у вас не будет проблем с повторным использованием вашего репозитория методы, поскольку они доступны из корня, плюс все задачи и транзакции. –