<commit_before>package committer

import (
	"fmt"
	"sync"

	. "github.com/divtxt/raft"
	"github.com/divtxt/raft/internal"
	"github.com/divtxt/raft/util"
)

type FatalErrorHandler func(err error)

// Committer is an implementation of the ICommitter internal interface.
//
// It is a goroutine that applies committed log entries to the state machine
// and notifying clients that are waiting for those entries to be committed.
//
type Committer struct {
	mutex sync.Mutex

	// -- Commit state
	// commitIndex is the index of highest log entry known to be committed
	// (initialized to 0, increases monotonically)
	commitIndex LogIndex

	// -- External components
	log          internal.LogTailOnlyRO
	stateMachine StateMachine
	feHandler    FatalErrorHandler

	// -- Internal components
	commitApplier *util.TriggeredRunner

	// -- Commit listeners
	listeners              map[LogIndex]chan CommandResult
	highestRegisteredIndex LogIndex
}

// NewCommitter creates a new Committer with the given parameters.
//
// A goroutine is started that applies committed log entries to the state machine and notifies
// clients that are waiting for those entries to be committed.
//
// If the goroutine sees an error this is fatal for it, and it will call fceListener instead of
// calling panic(). fceListener is expected to call the committer's StopSync() method before it
// returns!
//
func NewCommitter(
	log internal.LogTailOnlyRO,
	stateMachine StateMachine,
	feHandler FatalErrorHandler,
) *Committer {
	// TODO: check that parameters are not nil?!

	c := &Committer{
		mutex:                  sync.Mutex{},
		commitIndex:            0,
		log:                    log,
		stateMachine:           stateMachine,
		feHandler:              feHandler,
		commitApplier:          nil,
		listeners:              make(map[LogIndex]chan CommandResult),
		highestRegisteredIndex: 0,
	}
	c.commitApplier = util.NewTriggeredRunner(c.applyPendingCommits)

	return c
}

// StopSync will stop the Committer's goroutine.
//
// Will panic if called more than once.<commit_msg>Group Committer fields protected by lock and improve comments<commit_after>package committer

import (
	"fmt"
	"sync"

	. "github.com/divtxt/raft"
	"github.com/divtxt/raft/internal"
	"github.com/divtxt/raft/util"
)

type FatalErrorHandler func(err error)

// Committer is an implementation of the ICommitter internal interface.
//
// It is a goroutine that applies committed log entries to the state machine
// and notifying clients that are waiting for those entries to be committed.
//
type Committer struct {
	// -- Commit state
	// commitIndex is the index of highest log entry known to be committed
	// (initialized to 0, increases monotonically)
	mutex                  sync.Mutex
	commitIndex            LogIndex
	listeners              map[LogIndex]chan CommandResult // Commit listeners
	highestRegisteredIndex LogIndex

	// -- External components
	log          internal.LogTailOnlyRO
	stateMachine StateMachine
	feHandler    FatalErrorHandler

	// -- Internal components
	commitApplier *util.TriggeredRunner
}

// NewCommitter creates a new Committer with the given parameters.
//
// A goroutine is started that applies committed log entries to the state machine one at a time
// in order, and notifies the client that is waiting for that entry to be committed. This is
// driven asynchronously by calls to the CommitAsync method. See ICommitter for more details.
//
// If the goroutine sees an error, this is fatal for it. In this case, it will call feHandler
// with the encountered error. The feHandler callback is expected to call the Committer's
// StopSync() method before it returns. (or panics)
//
func NewCommitter(
	log internal.LogTailOnlyRO,
	stateMachine StateMachine,
	feHandler FatalErrorHandler,
) *Committer {
	// TODO: check that parameters are not nil?!

	c := &Committer{
		commitIndex:            0,
		log:                    log,
		stateMachine:           stateMachine,
		feHandler:              feHandler,
		commitApplier:          nil,
		listeners:              make(map[LogIndex]chan CommandResult),
		highestRegisteredIndex: 0,
	}
	c.commitApplier = util.NewTriggeredRunner(c.applyPendingCommits)

	return c
}

// StopSync will stop the Committer's goroutine.
//
// Will panic if called more than once.
{'fraction_non_alphanumeric': 0.07321053858708323, 'fraction_numerical': 0.0013989274889251574, 'mean_word_length': 3.0935114503816794, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '882934', 'n_tokens_mistral': 1217, 'n_tokens_neox': 1173, 'n_words': 451}