Rumah >pembangunan bahagian belakang >Golang >Menguji untuk mengendalikan pemasaan yang tidak tepat apabila membatalkan pertanyaan bernombor

Menguji untuk mengendalikan pemasaan yang tidak tepat apabila membatalkan pertanyaan bernombor

WBOY
WBOYke hadapan
2024-02-14 10:42:081001semak imbas

Menguji untuk mengendalikan pemasaan yang tidak tepat apabila membatalkan pertanyaan bernombor

Apabila melakukan pertanyaan pangkalan data, kami sering menghadapi pertanyaan paging. Walau bagaimanapun, apabila pertanyaan bernombor dibatalkan, ketidaktepatan masa kadangkala boleh berlaku. Isu ini penting untuk aplikasi yang memerlukan masa yang tepat. Dalam artikel ini, editor PHP Baicao akan memperkenalkan kepada anda cara menangani masalah ini untuk memastikan ketepatan dan ketepatan masa. Kami akan meneroka beberapa kemungkinan punca dan penyelesaian untuk membantu anda memahami dan menangani masalah ini dengan lebih baik.

Kandungan soalan

Saya mempunyai objek yang digunakan untuk membuat pertanyaan sql bernombor yang membolehkan untuk menjalankan pertanyaan secara tidak segerak:

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
    }
}

Saya cuba menguji kod ini, khususnya bahagian pembatalan. Kod ujian saya kelihatan seperti ini:

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

Masalah yang saya hadapi ialah ujian ini kadangkala gagal pada baris yang ditunjukkan oleh ulasan saya, kerana apabila cancel() dipanggil, tiada jaminan bahawa apabila saya menyemak tukar - ctx.done atau . Pelaksanaan boleh berlaku di mana-mana sahaja dalam gelung sehingga saya menghantar keputusan ke saluran <code>results. Tetapi itu tidak masuk akal kerana pelaksanaan harus disekat sehingga saya menerima data daripada saluran results, yang saya tidak akan lakukan sehingga saya memanggil cancel() . Selain itu, saya bergantung pada pakej sqlmock untuk ujian sql, yang tidak membenarkan apa-apa jenis pertanyaan sql kabur. Mengapa saya mendapat gangguan ini dan bagaimana saya membetulkannya? cancel() 时,不能保证在我检查 switch 语句处执行 - ctx.done 或 。执行可以在循环中的任何位置进行,直到我将结果发送到 <code>results 通道。但这没有意义,因为执行应该阻塞,直到我从 results 通道接收到数据,直到我调用 cancel() 后我才会这样做。此外,我依靠 sqlmock 包进行 sql 测试,它不允许对 sql 查询进行任何类型的模糊检查。为什么我会遇到此故障以及如何修复它?

解决方法

我的问题是由于我自己对 go 通道缺乏了解而导致的。我认为,通过创建 chan([]*t, 1) 意味着通道在满时(即当它包含单个项目时)会阻塞,但事实并非如此。相反,当我尝试在缓冲区已满时发送到通道时,会发生阻塞。因此,通过像这样修改 results

Penyelesaian

Masalah saya berpunca daripada kekurangan pemahaman saya sendiri tentang saluran go. Saya fikir bahawa dengan mencipta chan([]*t, 1) ia bermakna saluran akan disekat apabila penuh (iaitu apabila ia mengandungi satu item), tetapi ini tidak berlaku. Sebaliknya, apabila saya cuba menghantar ke saluran apabila penimbal penuh, penyekatan berlaku. Jadi dengan mengubah suai hasil seperti ini: 🎜
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,
    }
}
🎜Saya boleh memastikan saluran disekat sehingga data yang terkandung di dalamnya diterima. Perubahan ini menyelesaikan semua isu dengan ujian. 🎜

Atas ialah kandungan terperinci Menguji untuk mengendalikan pemasaan yang tidak tepat apabila membatalkan pertanyaan bernombor. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam