Skip to content

codeintel: Write to the lsif_commits table in a deterministic order

Administrator requested to merge commit-insertion-order into master

Created by: efritz

Reduce deadlock probability by always writing tuples in a deterministic order. This should (hopefully) make it impossible for two threads to be blocked on writing the same tuples.

This was tested with the following script. A deadlock occurred immediately on the first attempt without this change, and went a few dozen rounds without error afterwards:

func TestDeadlockPrevention(t *testing.T) {
	if testing.Short() {
		t.Skip()
	}
	dbtesting.SetupGlobalTestDB(t)
	db := testDB()

	commits := map[string][]string{}
	for i := 0; i < 10000; i++ {
		commits[makeCommit(i)] = []string{makeCommit(i + 1), makeCommit(i + 2)}
	}

	i := 0

	f := func() {
		errs := make(chan error)

		tx1, err1 := db.Transact(context.Background())
		if err1 != nil {
			t.Fatal(err1)
		}

		tx2, err2 := db.Transact(context.Background())
		if err2 != nil {
			t.Fatal(err2)
		}

		go func() {
			errs <- tx1.UpdateCommits(context.Background(), i, commits)
			errs <- tx1.Done(nil)
		}()

		go func() {
			errs <- tx2.UpdateCommits(context.Background(), i, commits)
			errs <- tx2.Done(nil)
		}()

		for i := 0; i < 4; i++ {
			if err := <-errs; err != nil {
				t.Fatal(err)
			}
		}
		close(errs)
	}

	for {
		f()
		i++
	}
}

Merge request reports

Loading