Ejemplo n.º 1
// NewWithID creates a new client connected to server available at
// addr, identifying using the custom id provided.
func NewWithID(addr string, id string, opts ...Option) (*Client, error) {
	var connectionOpts []connection.Option
	for _, opt := range opts {
		connectionOpts = append(connectionOpts, connection.Option(opt))

	conn, err := connection.New(addr, connectionOpts...)
	if err != nil {
		return nil, err

	client := &Client{
		id:              id,
		conn:            conn,
		resources:       make(map[string]*resourceImpl),
		newResource:     make(chan resourceAction),
		releaseResource: make(chan resourceAction),
		goRoutineHalted: make(chan bool),

	go client.run()

	return client, nil
Ejemplo n.º 2
// NewIntermediate creates a server connected to the lower level server.
func NewIntermediate(ctx context.Context, id string, addr string, leader election.Election, opts ...connection.Option) (*Server, error) {
	var (
		conn    *connection.Connection
		updater updater
		err     error

	isRootServer := addr == ""

	// Set up some configuration for intermediate server: establish a connection
	// to a lower-level server (e.g. the root server) and assign the updater function.
	if !isRootServer {
		if conn, err = connection.New(addr, opts...); err != nil {
			return nil, err

		updater = func(server *Server, retryNumber int) (time.Duration, int) {
			return server.performRequests(ctx, retryNumber)

	server := &Server{
		ID:             id,
		Election:       leader,
		isConfigured:   make(chan bool),
		resources:      make(map[string]*Resource),
		becameMasterAt: time.Unix(0, 0),
		conn:           conn,
		updater:        updater,
		quit:           make(chan bool),

	const (
		namespace = "doorman"
		subsystem = "server"

	labelNames := []string{"resource"}
	server.descs.has = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, subsystem, "has"),
		"All capacity assigned to clients for a resource.",
		labelNames, nil,
	server.descs.wants = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, subsystem, "wants"),
		"All capacity requested by clients for a resource.",
		labelNames, nil,
	server.descs.subclients = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, subsystem, "subclients"),
		"Number of clients requesting this resource.",
		labelNames, nil,

	// For an intermediate server load the default config for "*"
	// resource.  As for root server, this config will be loaded
	// from some external source..
	if !isRootServer {
		if err := server.LoadConfig(ctx, &pb.ResourceRepository{
			Resources: []*pb.ResourceTemplate{
		}, map[string]*time.Time{}); err != nil {
			return nil, err

	go server.run()

	return server, nil