package models import ( "fmt" "sync" "github.com/MichaelMure/git-bug/cache" "github.com/MichaelMure/git-bug/entities/identity" "github.com/MichaelMure/git-bug/entity" ) // IdentityWrapper is an interface used by the GraphQL resolvers to handle an identity. // Depending on the situation, an Identity can already be fully loaded in memory or not. // This interface is used to wrap either a lazyIdentity or a loadedIdentity depending on the situation. type IdentityWrapper interface { Id() entity.Id Name() string Email() (string, error) Login() (string, error) AvatarUrl() (string, error) Keys() ([]*identity.Key, error) DisplayName() string IsProtected() (bool, error) } var _ IdentityWrapper = &lazyIdentity{} type lazyIdentity struct { cache *cache.RepoCache excerpt *cache.IdentityExcerpt mu sync.Mutex id *cache.IdentityCache } func NewLazyIdentity(cache *cache.RepoCache, excerpt *cache.IdentityExcerpt) *lazyIdentity { return &lazyIdentity{ cache: cache, excerpt: excerpt, } } func (li *lazyIdentity) load() (*cache.IdentityCache, error) { li.mu.Lock() defer li.mu.Unlock() if li.id != nil { return li.id, nil } id, err := li.cache.Identities().Resolve(li.excerpt.Id()) if err != nil { return nil, fmt.Errorf("cache: missing identity %v", li.excerpt.Id()) } li.id = id return id, nil } func (li *lazyIdentity) Id() entity.Id { return li.excerpt.Id() } func (li *lazyIdentity) Name() string { return li.excerpt.Name } func (li *lazyIdentity) DisplayName() string { return li.excerpt.DisplayName() } func (li *lazyIdentity) Email() (string, error) { id, err := li.load() if err != nil { return "", err } return id.Email(), nil } func (li *lazyIdentity) Login() (string, error) { id, err := li.load() if err != nil { return "", err } return id.Login(), nil } func (li *lazyIdentity) AvatarUrl() (string, error) { id, err := li.load() if err != nil { return "", err } return id.AvatarUrl(), nil } func (li *lazyIdentity) Keys() ([]*identity.Key, error) { id, err := li.load() if err != nil { return nil, err } return id.Keys(), nil } func (li *lazyIdentity) IsProtected() (bool, error) { id, err := li.load() if err != nil { return false, err } return id.IsProtected(), nil } var _ IdentityWrapper = &loadedIdentity{} type loadedIdentity struct { identity.Interface } func NewLoadedIdentity(id identity.Interface) *loadedIdentity { return &loadedIdentity{Interface: id} } func (l loadedIdentity) Email() (string, error) { return l.Interface.Email(), nil } func (l loadedIdentity) Login() (string, error) { return l.Interface.Login(), nil } func (l loadedIdentity) AvatarUrl() (string, error) { return l.Interface.AvatarUrl(), nil } func (l loadedIdentity) Keys() ([]*identity.Key, error) { return l.Interface.Keys(), nil } func (l loadedIdentity) IsProtected() (bool, error) { return l.Interface.IsProtected(), nil }