이해하기 Golang 워커 패턴
Source: Dev.to
워커 생성
intNumWorkers := 3
for w := 0; w < intNumWorkers; w++ {
go InsertStudentData(ctx, tx, insertedStudentJobs, insertedStudentjobsErrCh)
}
func InsertStudentData(ctx context.Context, tx *sql.Tx, data <-chan models.StudentItem, errCh chan<- error) {
// worker implementation
}
세 개의 goroutine 워커가 시작됩니다; 각각 StudentItem 값 채널을 읽고 errCh를 통해 오류를 보고합니다.
워커에게 작업/잡 퍼블리시
numJobs := len(StudentItems)
jobs := make(chan models.StudentItem, numJobs)
for i := 0; i < numJobs; i++ {
jobs <- StudentItems[i]
}
close(jobs)
func InsertStudentWorker(ctx context.Context, tx *sql.Tx, data <-chan models.StudentItem, errCh chan<- error) {
for d := range data {
err := repository.InsertStudentItemFromWorker(ctx, tx, d)
// handle err if needed
}
}
호출자는 버퍼링된 채널에 모든 StudentItem 작업을 채운 뒤 채널을 닫습니다. 워커들은 이 읽기 전용 채널(data <-chan models.StudentItem)에서 작업을 가져와 동시에 처리합니다.
결과 수집
numJobs := len(StudentItems)
jobs := make(chan models.StudentItem, numJobs)
for i := 0; i < numJobs; i++ {
jobs <- StudentItems[i]
}
close(jobs)
// read from the error channel
for j := 0; j < numJobs; j++ {
err := <-jobsErrCh
if err != nil {
_ = tx.Rollback()
return err
}
}
func InsertStudentWorker(ctx context.Context, tx *sql.Tx, data <-chan models.StudentItem, errCh chan<- error) {
for d := range data {
err := repository.InsertStudentItemFromWorker(ctx, tx, d)
errCh <- err
}
}
각 워커는 자신의 결과(또는 오류)를 쓰기 전용 채널(errCh)에 보냅니다. 호출자는 배포된 작업 수를 알고 있기 때문에 정확히 그 수만큼 결과를 읽어 오류를 처리하며, 어느 워커가 오류를 발생시켰는지는 알 필요가 없습니다.