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

Code before:

type Options struct {
	AuditWriter    io.Writer
	NoUpgrade      bool
	ProfilerAddr   string
	ResetDeltaIdxs bool
	Verbose        bool
	// null duration means use default value
	DBRecheckInterval    time.Duration
	DBIndirectGCInterval time.Duration
}

type App struct {
	myID              protocol.DeviceID
	mainService       *suture.Supervisor
	cfg               config.Wrapper
	ll                *db.Lowlevel
	evLogger          events.Logger
	cert              tls.Certificate
	opts              Options
	exitStatus        svcutil.ExitStatus
	err               error
	stopOnce          sync.Once
	mainServiceCancel context.CancelFunc
	stopped           chan struct{}
}

func New(cfg config.Wrapper, dbBackend backend.Backend, evLogger events.Logger, cert tls.Certificate, opts Options) (*App, error) {
	ll, err := db.NewLowlevel(dbBackend, evLogger, db.WithRecheckInterval(opts.DBRecheckInterval), db.WithIndirectGCInterval(opts.DBIndirectGCInterval))
	if err != nil {
		return nil, err
	}
	a := &App{
		cfg:      cfg,
		ll:       ll,
		evLogger: evLogger,
		opts:     opts,
		cert:     cert,
		stopped:  make(chan struct{}),
	}
	close(a.stopped) // Hasn't been started, so shouldn't block on Wait.
	return a, nil
}

// Start executes the app and returns once all the startup operations are done,
// e.g. the API is ready for use.
// Must be called once only.
func (a *App) Start() error {
	// Create a main service manager. We'll add things to this as we go along.
	// We want any logging it does to go through our log system.
	spec := svcutil.SpecWithDebugLogger(l)

Review comment (suggestion):
I am a bit late: I'd rather not expose the entirety of the model interface here. For example we definitely don't want anyone to use the suture service methods - there are dedicated methods to start/stop `App`. Lets make the model member internal and expose just the methods you need.

Code after:

type Options struct {
	AuditWriter    io.Writer
	NoUpgrade      bool
	ProfilerAddr   string
	ResetDeltaIdxs bool
	Verbose        bool
	// null duration means use default value
	DBRecheckInterval    time.Duration
	DBIndirectGCInterval time.Duration
}

type App struct {
	myID              protocol.DeviceID
	mainService       *suture.Supervisor
	cfg               config.Wrapper
	ll                *db.Lowlevel
	evLogger          events.Logger
	cert              tls.Certificate
	opts              Options
	exitStatus        svcutil.ExitStatus
	err               error
	stopOnce          sync.Once
	mainServiceCancel context.CancelFunc
	stopped           chan struct{}
	Model             model.Model
}

func New(cfg config.Wrapper, dbBackend backend.Backend, evLogger events.Logger, cert tls.Certificate, opts Options) (*App, error) {
	ll, err := db.NewLowlevel(dbBackend, evLogger, db.WithRecheckInterval(opts.DBRecheckInterval), db.WithIndirectGCInterval(opts.DBIndirectGCInterval))
	if err != nil {
		return nil, err
	}
	a := &App{
		cfg:      cfg,
		ll:       ll,
		evLogger: evLogger,
		opts:     opts,
		cert:     cert,
		stopped:  make(chan struct{}),
	}
	close(a.stopped) // Hasn't been started, so shouldn't block on Wait.
	return a, nil
}

// Start executes the app and returns once all the startup operations are done,
// e.g. the API is ready for use.
// Must be called once only.
func (a *App) Start() error {
	// Create a main service manager. We'll add things to this as we go along.
	// We want any logging it does to go through our log system.