在進行資料庫查詢時,我們常常會遇到分頁查詢的情況。然而,當取消分頁查詢時,有時會導致計時不準確的問題。這個問題對於需要精確計時的應用程式來說是非常關鍵的。在本文中,php小編百草將為您介紹如何處理這個問題,從而確保計時的準確性和精確性。我們將探討一些可能的原因和解決方案,幫助您更好地理解和應對這個問題。
我有一個物件用於進行分頁 sql 查詢,該查詢允許非同步執行查詢:
type pagedquery[t any] struct { results chan []*t errors chan error done chan error quit chan error client *sql.db } func newpagedquery[t any](client *sql.db) *pagedquery[t] { return &pagedquery[t]{ results: make(chan []*t, 1), errors: make(chan error, 1), done: make(chan error, 1), quit: make(chan error, 1), client: client, } } func (paged *pagedquery[t]) requestasync(ctx context.context, queries ...*query) { conn, err := client.conn(ctx) if err != nil { paged.errors <- err return } defer func() { conn.close() paged.done <- nil }() for i, query := range queries { select { case <-ctx.done(): return case <-paged.quit: return default: } rows, err := conn.querycontext(ctx, query.string, query.arguments...) if err != nil { paged.errors <- err return } data, err := sql.readrows[t](rows) if err != nil { paged.errors <- err return } paged.results <- data } }
我正在嘗試測試此程式碼,特別是取消部分。我的測試程式碼如下所示:
svc, mock := createServiceMock("TEST_DATABASE", "TEST_SCHEMA") mock.ExpectQuery(regexp.QuoteMeta("TEST QUERY")). WithArgs(...). WillReturnRows(mock.NewRows([]string{"t", "v", "o", "c", "h", "l", "vw", "n"})) ctx, cancel := context.WithCancel(context.Background()) go svc.requestAsync(ctx, query1, query2, query3, query4) time.Sleep(50 * time.Millisecond) cancel() results := make([]data, 0) loop: for { select { case <-query.Done: break loop case err := <-query.Errors: Expect(err).ShouldNot(HaveOccurred()) case r := <-query.Results: results = append(results, r...) } } Expect(results).Should(BeEmpty()) Expect(mock.ExpectationsWereMet()).ShouldNot(HaveOccurred()) // fails here
我遇到的問題是,此測試偶爾會在我的評論所指示的行處失敗,因為當調用cancel()
時,不能保證在我檢查switch
語句處執行- ctx.done 或。執行可以在循環中的任何位置進行,直到我將結果發送到 <code>results
通道。但這沒有意義,因為執行應該阻塞,直到我從 results
通道接收到數據,直到我調用 cancel()
後我才會這樣做。此外,我依靠 sqlmock 套件進行 sql 測試,它不允許對 sql 查詢進行任何類型的模糊檢查。為什麼我會遇到此故障以及如何修復它?
我的問題是由於我自己對 go 通道缺乏了解而導致的。我認為,透過建立 chan([]*t, 1)
意味著通道在滿時(即當它包含單一項目時)會阻塞,但事實並非如此。相反,當我嘗試在緩衝區已滿時發送到通道時,會發生阻塞。因此,透過像這樣修改 results
:
func NewPagedQuery[T any](client *sql.DB) *PagedQuery[T] { return &PagedQuery[T]{ Results: make(chan []*T), // Remove buffer here Errors: make(chan error, 1), Done: make(chan error, 1), Quit: make(chan error, 1), client: client, } }
我可以確保通道阻塞,直到接收到它包含的資料。這項變更解決了測試的所有問題。
以上是測試取消分頁查詢時處理不精確的計時的詳細內容。更多資訊請關注PHP中文網其他相關文章!