Repository: syncthing/syncthing
File: lib/model/folder_sendrecv.go (Go)

Code before:

	// Signal copy and puller routines that we are done with the in data for
	// this iteration. Wait for them to finish.
	close(copyChan)
	copyWg.Wait()
	close(pullChan)
	pullWg.Wait()

	// Signal the finisher chan that there will be no more input and wait
	// for it to finish.
	close(finisherChan)
	doneWg.Wait()

	if err == nil {
		f.processDeletions(fileDeletions, dirDeletions, dbUpdateChan, scanChan)
	}

	// Wait for db updates and scan scheduling to complete
	close(dbUpdateChan)
	updateWg.Wait()

	return changed
}

func (f *sendReceiveFolder) processNeeded(dbUpdateChan chan<- dbUpdateJob, copyChan chan<- copyBlocksState, scanChan chan<- string) (int, map[string]protocol.FileInfo, []protocol.FileInfo, error) {
	changed := 0
	var dirDeletions []protocol.FileInfo
	fileDeletions := map[string]protocol.FileInfo{}
	buckets := map[string][]protocol.FileInfo{}

	// Iterate the list of items that we need and sort them into piles.
	// Regular files to pull goes into the file queue, everything else
	// (directories, symlinks and deletes) goes into the "process directly"
	// pile.
	f.fset.WithNeed(protocol.LocalDeviceID, func(intf db.FileIntf) bool {
		select {
		case <-f.ctx.Done():
			return false
		default:
		}

		if f.IgnoreDelete && intf.IsDeleted() {
			l.Debugln(f, "ignore file deletion (config)", intf.FileName())
			return true
		}

		file := intf.(protocol.FileInfo)

		switch {
		case f.ignores.ShouldIgnore(file.Name):
			file.SetIgnored(f.shortID)

Review comment (suggestion):
This seems to cause problems now, as I'm explaining [here](https://github.com/syncthing/syncthing/issues/6219#issuecomment-570759947), as `/rest/db/need` call relies on the queue to be up-to-date all the time, not only why processed by `processNeeded`. Is there a reason we need "defer" here at all, and not just plain `f.queue.Reset` so that it's done before the processing and not after? This way the queue will be correct most of the time.  @imsodin @calmh 

Code after:

	// Signal copy and puller routines that we are done with the in data for
	// this iteration. Wait for them to finish.
	close(copyChan)
	copyWg.Wait()
	close(pullChan)
	pullWg.Wait()

	// Signal the finisher chan that there will be no more input and wait
	// for it to finish.
	close(finisherChan)
	doneWg.Wait()

	if err == nil {
		f.processDeletions(fileDeletions, dirDeletions, dbUpdateChan, scanChan)
	}

	// Wait for db updates and scan scheduling to complete
	close(dbUpdateChan)
	updateWg.Wait()

	return changed
}

func (f *sendReceiveFolder) processNeeded(dbUpdateChan chan<- dbUpdateJob, copyChan chan<- copyBlocksState, scanChan chan<- string) (int, map[string]protocol.FileInfo, []protocol.FileInfo, error) {
	defer f.queue.Reset()

	changed := 0
	var processDirectly []protocol.FileInfo
	var dirDeletions []protocol.FileInfo
	fileDeletions := map[string]protocol.FileInfo{}
	buckets := map[string][]protocol.FileInfo{}

	// Iterate the list of items that we need and sort them into piles.
	// Regular files to pull goes into the file queue, everything else
	// (directories, symlinks and deletes) goes into the "process directly"
	// pile.
	f.fset.WithNeed(protocol.LocalDeviceID, func(intf db.FileIntf) bool {
		select {
		case <-f.ctx.Done():
			return false
		default:
		}

		if f.IgnoreDelete && intf.IsDeleted() {
			l.Debugln(f, "ignore file deletion (config)", intf.FileName())
			return true
		}

		file := intf.(protocol.FileInfo)