model

package
v0.0.0-...-176f8cf Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 18, 2020 License: MIT Imports: 17 Imported by: 0

README

FAQ

Q1: ¿Cómo y cuando se actualiza el número total de invitados (num_guests) y de asistentes (num_attendees)?

R1: Ambos son valores precalculados bien cuando se crea o modifica un evento, o cuando se lee de la base de datos. El número total de invitados se actualiza la primera vez que se crea el evento. Posteriormente, si se modifica el evento, el número total de invitados se actualizará también. En cuanto a num_attendees, inicialmente es 0 al crear el evento. Si se modifica un evento que ya tenía participantes confirmados el evento modificado tendrá el valor correcto. En ambos casos, tanto num_guests como num_attendees será correctos en el momento de leerse el evento de la base de datos.

--

Q2: ¿Qué pasa si se añaden nuevos invitados a un evento existente desde dos lugares a la vez?

R2: Desde el punto de vista de la base de datos no habría problemas de inconsistencia. Cada participante ocupa su propia fila dentro de la partición por lo que, siempre y cuando no se sobrescriba su respuesta o estado, no habría problemas en añadir usuarios al evento desde más de un lugar a la vez (ni siquiera cuando algunos usuarios coincidan).

Desde el punto de vista del objeto en memoria la cosa cambia. En este caso, si dos usuarios A y B invitan a sus amigos a un evento al mismo tiempo, asumiendo 3 invitados iniciales, que los nuevos invitados son distintos y que A invita a 3 usuarios y B invita a 4 usuarios, inicialmente al leer el evento de la base de datos, el objeto en memoria será consistente para ambos usuarios. Sin embargo tras modificarse el evento, el objeto en memoria del usuario A tendrá 6 invitados, mientras que el usuario B tendrá 7 invitados. En este caso, cuando el servidor envia el evento al usuario A y usuario B, sus bases de datos podrían ser inconsistentes.

Dado que el problema reside en que el objeto en memoria es diferente y que este puede llegar a transmitirse por la red a otros clientes, la solución pasaría aquí por enviar únicamente la información que ha cambiado y incluir un número de versión. De este modo, el usuario A únicamente enviaría que ha añadido a 2 usuarios y el usuario B únicamente enviaría que ha añadido a 3 usuarios. Cuando ambos mensajes lleguen a todos los participantes del evento, el resultado será que hay 5 usuarios nuevos, además de los 3 que ya tenían. Por tanto, los clientes y la base de datos del servidor estarán sincronizados.

--

Q3: ¿Qué pasa si se modifica el mismo evento desde dos sitios a la vez?

R3: La información del evento sería la de la última escritura en producirse. Si dos usuarios A y B modifican un evento al mismo tiempo, al enviarse la información al resto de participantes del evento algunos de estos llegarían a tener un estado inconsistente dependiendo del orden de llegada de los mensajes. Si por ejemplo la base de datos si hubiera quedado en el estado puesto por B, si un cliente recibe primero el mensaje del usuario B y luego el de A, la base de datos del cliente sería inconsistente.

Al igual que en el caso anterior, la solución pasa por controlar y versionar la información que se transmite al cliente para que este pueda decidir qué cambios aplica y cuales no. En este caso, todos los campos que componen la información del evento (description, start date, end date, event state y position) se escribirán en bloque. De este modo, el evento no podrá contener alguna información modificada por el usuario A y otra por el usuario B. Es decir, si el cliente A modifica la descripción y el cliente B modifica la fecha y la hora, nunca se realizará la mezcla de ambos cambios.

Otra solución a este problema es hacer que la escritura que llegue primero se haga efectiva, mientras que la segunda escritura reciba un error avisando de que la copia que intenta modificar ya no existe y por tanto debe volver a leer el evento.

--

Q4: ¿Qué pasa si se modifica un evento mientras un participante cambia su respuesta?

R4: La información que se puede modificar de un participante no solapa con la información que se puede modificar del evento. En concreto, durante la modificación del evento solo se pueden añadir nuevos participantes que se traduce en añadir una nueva fila (única para cada participante) a la lista de participantes del evento en la base de datos. Mientras que el cambio de respuesta o estado de un participante modificaría, dentro de una fila existente, la columna correspondiente. Si la misma fila y columna (celda) se modifican a la vez, la última escritura gana. En resumen, se pueden añadir nuevas participantes y modificar la respuesta o estado de un participante existente al mismo tiempo y sin se produzca ninguna inconsistencia en la base de datos.

No obstante, el objeto en memoria del evento modificado si que sería inconsistente dado que, si la respuesta de un participante cambió después de haberse leído el evento, el evento en memoria contendrá información sin actualizar. De nuevo, esto hay que tenerlo en cuenta si se decide transmitir al cliente el evento en memoria pues, al ser inconsistente, trasladaría dicha inconsistencia a la base de datos de los clientes. En este caso, si el cliente recibe primero la modificación del evento y luego el cambio en la respuesta, la información en el cliente será consistente con la del servidor. Si se recibe primero el cambio en la respuesta y luego la modificación ¡¡la información sería inconsistente!!

Como ya se ha comentado, una solución a este problema sería versionar los cambios de estado de cada participante. De este modo, el cliente podrá decidir ignorar cambios anteriores si la versión actual es superior y solo aplicar cambios con un número de version mayor que la actual.

NOTA: Si la información de un mismo participante cambia desde dos sitios a la vez, la última operación de escritura será la que se mantenga. Esto no es un problema ya que solo un participante puede cambiar su respuesta en el evento.

--

Q5: Cuando cambio el estado o la respuesta de un participante ¿debo actualizar también el evento asociado si ha sido cargado previamente?

R5: En el momento en que la información de un evento se lee de la base de datos, esta es consistente. Si el participante de un evento cambia de estado, naturalmente un evento leído previamente sería inconsistente con la información en la base de datos. En el caso de que el evento se modifique esto no supone ningún inconveniente ya que ninguna modificación del evento puede cambiar el estado del participante. El único caso en que puede resultar en inconsistencias sería si el evento se envía al cliente ya que estaría transmitiendo información antigua. En este caso, si se versiona el estado del participante el cliente podrá aplicar únicamente la información más actual e ignorar la antigua.

--

Q6: ¿Quién se encarga de leer los próximos eventos en RAM para poblar los próximos eventos de cada usuario y los eventos activos?

R6:

--

Q7: ¿Tiene sentido devolver copia del evento y no trabajar sobre el evento existente?

R7: La inmutabilidad es una propiedad deseable dentro de un sistema concurrente para evitar condiciones de carrera. Del mismo modo, al tratarse también de un sistema distribuido no tiene sentido que todos los nodos compartan el mismo espacio de eventos en memoria. Esto implica que los cambios de un evento en la memoria de un nodo no se sincronizan con el mismo evento en la memoria de otro nodo, ni siquiera dentro del mismo nodo. Es decir, en un mismo instante t dos nodos cualesquiera pueden tener en memoria una versión diferente del mismo evento. No obstante, los casos en los que esto puede suceder son limitados y no provocan efectos secundarios:

a) cassandra tiene consistencia 'eventually consistency'. Cuando las escrituras en un evento aún no se han propagado por todos los nodos una lectura posterior a la escritura aún puede recuperar una versión anterior de un evento;

b) cuando dos nodos leen la misma versión de un evento pero ambos la modifican. Esto provoca que cada nodo tenga un evento diferente en su memoria RAM. Sin embargo, no supone un problema dado que al escribir el evento en la base de datos la última escritura será la que prevalezca. NOTA: La escritura que fue inmediatamente sobrescrita no recibiría ningún error. Por lo que respecta al cliente se realizó correctamente. !!!! REVISAR !!!!

c) cuando un nodo lee un evento en RAM y otro nodo modifica y guarda el estado de un participante del mismo evento. Como la información del participante forma parte del evento, el evento en RAM del primer nodo será inconsistente con lo que hay realmente en la base de datos. Esto tampoco supone un problema porque si se envía el evento al cliente, el estado del participante estará versionado.

--

Q8: ¿Qué pasa si se modifica un evento en RAM y se envía al cliente antes de guardarse en la base de datos?

R8: En este caso, cuando se modifica el evento su versión será indeterminada hasta que el evento se guarde en la base de datos. De este modo, si el evento se envía al cliente este lo ignoraría al no poder decidir si aplicar el cambio o descartarlo.

--

Q9: En el caso de los builders que modifican un objeto, ¿debe poder devolver un error en algún caso concreto o el responsable de todo es la llamada a Build?

R9: - La llamada a Build() es la que construye el objeto y la que debe comprobar cualquier otra condición, por tanto es la responsable de generar el error. No obstante, en algunos casos es interesante poder devolver también un error antes de llegar siquiera a obtener un constructor. Por ejemplo, si el evento ya ha empezado y, por tanto, no se debe poder modificar.

--

Q10: ¿Qué pasa si un usuario sube la misma imagen dos veces?

R10: Un mismo usuario no debería tener la misma imagen repetida en sus blobs

*/

/*

REQUISITOS

  • Todos los objetos que puedan leerse de la base de datos deben tener un flag (loaded) que indique si la instancia ha sido recuperada de la base de datos o no. Esto determinará al guardar dicho objeto si se guarda como uno nuevo o debe modificarse el existente.

  • Cuando se modifica un objeto, debe añadirse una lista con el atributo que se ha modificado y su antiguo valor. Esto será útil en ocasiones donde haya que actualizar una instancia antigua con una recien modificada. */

/*

  • Example: Load an event */ storedEvent, err := model.EventManager.LoadEvent(event_id)

/*

  • Example: Load multiple events */ storedEvent, err := model.EventManager.LoadAllEvents(id1, id2, id2, ...)

/*

  • Example: Create a new event */ newEvent, err := model.EventManager.NewEvent() // Returns an EventBuilder .SetAuthor(author) .SetCreatedDate(cd) // Optional, current date by default .SetModificationDate(md) // Optional, created date by default .SetStartDate(sd) .SetEndDate(ed) .SetDescription(d) .AddParticipant(userID1) .AddParticipant(userID2) .SetCancelled(true) // Optional, false by default .Build() // Checks are performed here, trigger error earlier as possible

storedEvent, err := model.EventManager.SaveEvent(newEvent) // Checks are performed here again (maybe not all of them)

/*

  • Example: Modify an event */ storedEvent, err := model.EventManager.LoadEvent(event_id) modEvent, err := model.EventManager.ModifyEvent(storedEvent) // Returns an EventBuilder (with other defaults) .SetStartDate(cd) .SetEndDate(ed) .SetModificationDate(md) // Optional, current date by default .SetDescription(d) .SetCancelled(true) // Optional, false by default .AddParticipant(userID3) .Build()

storedEvent, err := model.EventManager.SaveEvent(modEvent)

/*

  • Example: Attach image to an existing event */

// Create a new blob blob, err := model.BlobManager.New(imageBytes) err := model.BlobManager.Save(blob)

// or load an existing one blob, err := model.BlobManager.Load(blobID)

// Attach it to an existing event storedEvent, err := model.EventManager.LoadEvent(event_id) modEvent, err := model.EventManager.ModifyEvent(storedEvent) .AttachImage(blob, model.MainImage) .Build() // Triggers an error if blob is not saved in DB before attach to event storedEvent, err := model.EventManager.Save(modEvent) // Triggers an error if blob is not saved in DB before attach to event

/*

  • Example: Read image of an existing event */ storedEvent, err := model.EventManager.LoadEvent(event_id) blobID := storedEvent.Blob(model.MainImage) blob, err := model.BlobManager.Load(blobID) // blob.Data() contains binary data

/*

  • Example: Read participants */ storedEvent, err := model.EventManager.LoadEvent(event_id) for _, p := storedEvent.Participants() { fmt.Println(p.Id(), p.Name(), p.Response(), p.Status()) }

/*

  • Example: Change participant */ p, err := model.EventManager.LoadParticipant(user_id, event_id) newP, err := model.EventManager.ModifyParticipant(p) // Returns ParticipantBuilder .SetResponse(...) .SetStatus(...) .Build()

storedP, err := model.EventManager.SaveParticipant(newP) // TODO: Should also change any event previously loaded?

/*

  • Example: Read recent events for a user */ events, err := model.EventManager.LoadRecentEventsForUser(userID)

/*

  • Example: Read events history for a user */ option := model.ReadBackward // or model.ReadForward events, err := model.EventManager.LoadEventsHistoryForUser(userID, fromDate, option)

Documentation

Index

Constants

View Source
const (

	// User account
	UserPasswordMinLength = 5
	UserPasswordMaxLength = 50
	UserNameMinLength     = 3
	UserNameMaxLength     = 50
	UserPictureMaxWidth   = 512
	UserPictureMaxHeight  = 512
)
View Source
const (
	MinimumStartDate = DateOption(0)
	MaximumStartDate = DateOption(1)
	MinimumEndDate   = DateOption(2)
	MaximumEndDate   = DateOption(3)
)

DateOption values

Variables

View Source
var (
	ErrNotFound = api.ErrNotFound

	// User Account
	ErrInvalidEmail    = errors.New("invalid e-mail address")
	ErrInvalidName     = errors.New("invalid user name")
	ErrInvalidPassword = errors.New("password is too short")
	ErrNoCredentials   = errors.New("no credentials")

	// Event
	ErrInvalidEvent         = errors.New("event is invalid")
	ErrInvalidOwner         = errors.New("invalid owner")
	ErrInvalidAuthor        = errors.New("invalid author")
	ErrInvalidParticipant   = errors.New("invalid participant")
	ErrInvalidDescription   = errors.New("invalid event description")
	ErrInvalidStartDate     = errors.New("invalid start date")
	ErrInvalidEndDate       = errors.New("invalid end date")
	ErrParticipantsRequired = errors.New("participants required")
	ErrCannotArchive        = errors.New("cannot archive event")

	ErrModelInitError        = errors.New("model init error")
	ErrModelAlreadyExist     = errors.New("cannot register model because it already exists")
	ErrModelNotFound         = errors.New("model not found")
	ErrModelInconsistency    = errors.New("Model has an inconsistency that requires admin fixes")
	ErrImageOutOfBounds      = errors.New("image is out of bounds")
	ErrInvalidUserOrPassword = errors.New("invalid user or password")

	ErrEventOutOfCreationWindow  = errors.New("event out of allowed creation window")
	ErrEventNotWritable          = errors.New("event isn't writable")
	ErrParticipantNotFound       = errors.New("participant not found")
	ErrEmptyInbox                = errors.New("user inbox is empty")
	ErrAlreadyFriends            = errors.New("already friends")
	ErrFriendRequestAlreadyExist = errors.New("friend request already exists")

	ErrAccountNotLinkedToFacebook = errors.New("account isn't linked to facebook")

	ErrIllegalArgument = errors.New("illegal argument")
	ErrMissingArgument = errors.New("missing arguments")
	ErrNotImplemented  = errors.New("Method not implemented")
)

Functions

func FriendKeys

func FriendKeys(m []*Friend) []int64

func GetDateOption

func GetDateOption(option DateOption, fromDate time.Time) time.Time

func IsValidDescription

func IsValidDescription(description string) bool

func IsValidEndDate

func IsValidEndDate(endDate time.Time, referenceDate time.Time) bool

func IsValidName

func IsValidName(name string) bool

func IsValidPassword

func IsValidPassword(password string) bool

func IsValidStartDate

func IsValidStartDate(startDate time.Time, referenceDate time.Time) bool

func ParticipantMapKeys

func ParticipantMapKeys(m map[int64]*Participant) []int64

func UserMapKeys

func UserMapKeys(m map[int64]*UserAccount) []int64

Types

type AccessToken

type AccessToken struct {
	// contains filtered or unexported fields
}

func (*AccessToken) AsDTO

func (t *AccessToken) AsDTO() *api.AccessTokenDTO

func (*AccessToken) Token

func (t *AccessToken) Token() string

func (*AccessToken) UserID

func (t *AccessToken) UserID() int64

type AccountManager

type AccountManager struct {
	// contains filtered or unexported fields
}

func (*AccountManager) AuthenticateUser

func (self *AccountManager) AuthenticateUser(userId int64, authToken string) (bool, error)

func (*AccountManager) ChangePassword

func (m *AccountManager) ChangePassword(user *UserAccount, newPassword string) error

func (*AccountManager) ChangeProfilePicture

func (self *AccountManager) ChangeProfilePicture(user *UserAccount, picture []byte) error

Change profile picture in order to let user's friends to see the new picture

func (*AccountManager) CreateUserAccount

func (m *AccountManager) CreateUserAccount(name string, email string, password string, phone string, fbId string, fbToken string) (*UserAccount, error)

Prominent Errors: - ErrInvalidName - ErrInvalidEmail - ErrInvalidPassword - ErrNoCredentials - facebook.ErrFacebookAccessForbidden

func (*AccountManager) GetActiveSessions

func (m *AccountManager) GetActiveSessions(forDay time.Time) ([]*api.ActiveSessionInfoDTO, error)

func (*AccountManager) GetPushToken

func (self *AccountManager) GetPushToken(userId int64) (*IIDToken, error)

func (*AccountManager) GetUserAccount

func (self *AccountManager) GetUserAccount(userId int64) (*UserAccount, error)

func (*AccountManager) GetUserAccountByEmail

func (self *AccountManager) GetUserAccountByEmail(email string) (*UserAccount, error)

func (*AccountManager) GetUserAccountByFacebook

func (self *AccountManager) GetUserAccountByFacebook(fbId string) (*UserAccount, error)

func (*AccountManager) LinkToFacebook

func (self *AccountManager) LinkToFacebook(account *UserAccount, fbId string, fbToken string) error

func (*AccountManager) NewAuthCredentialByEmailAndPassword

func (self *AccountManager) NewAuthCredentialByEmailAndPassword(email string, password string) (*AccessToken, error)

Prominent Errors: - ErrInvalidUserOrPassword - Others (except dao.ErrNotFound)

func (*AccountManager) NewAuthCredentialByFacebook

func (m *AccountManager) NewAuthCredentialByFacebook(fbId string, fbToken string) (*AccessToken, error)

Prominent Errors: - fb.ErrFacebookAccessForbidden - ErrInvalidUserOrPassword - ErrModelInconsistency - Others (except dao.ErrNotFound)

func (*AccountManager) NewImageAccessToken

func (m *AccountManager) NewImageAccessToken(userID int64) (*AccessToken, error)

func (*AccountManager) Observe

func (m *AccountManager) Observe() observer.Stream

func (*AccountManager) RefreshSessionActivity

func (m *AccountManager) RefreshSessionActivity(userId int64) error

func (*AccountManager) SetFacebookAccessToken

func (m *AccountManager) SetFacebookAccessToken(user *UserAccount, accessToken string) error

func (*AccountManager) SetPushToken

func (m *AccountManager) SetPushToken(userID int64, pushToken *IIDToken) error

type AyiModel

type AyiModel struct {
	sync.RWMutex

	Accounts *AccountManager
	Events   *EventManager
	Friends  *FriendManager
	// contains filtered or unexported fields
}

func Get

func Get(key string) *AyiModel

Gets an already existing model and panic if model does not exist

func New

func New(session api.DbSession, key string) *AyiModel

Creates a new model with the given key for later retrieval. If model exist panic

func (*AyiModel) DbSession

func (m *AyiModel) DbSession() api.DbSession

func (*AyiModel) GetClosestDpi

func (self *AyiModel) GetClosestDpi(reqDpi int32) int32

func (*AyiModel) StartBackgroundTasks

func (m *AyiModel) StartBackgroundTasks()

Start init background and start tasks required for this model to work over time

type DateOption

type DateOption int

DateOption enum

type EmailCredential

type EmailCredential struct {
	Email    string
	Password [32]byte
	Salt     [32]byte
}

type Event

type Event struct {
	Participants *ParticipantList
	// contains filtered or unexported fields
}

func (*Event) AsDTO

func (e *Event) AsDTO() *api.EventDTO

func (*Event) AuthorID

func (e *Event) AuthorID() int64

func (*Event) AuthorName

func (e *Event) AuthorName() string

func (*Event) Clone

func (e *Event) Clone() *Event

func (*Event) CloneWithEmptyParticipants

func (e *Event) CloneWithEmptyParticipants() *Event

func (*Event) CreatedDate

func (e *Event) CreatedDate() time.Time

func (*Event) Description

func (e *Event) Description() string

func (*Event) EndDate

func (e *Event) EndDate() time.Time

func (*Event) Equal

func (e *Event) Equal(other *Event) bool

func (*Event) Id

func (e *Event) Id() int64

func (*Event) InboxPosition

func (e *Event) InboxPosition() time.Time

func (*Event) IsCancelled

func (e *Event) IsCancelled() bool

func (*Event) IsZero

func (e *Event) IsZero() bool

func (*Event) ModifiedDate

func (e *Event) ModifiedDate() time.Time

func (*Event) NumAttendees

func (e *Event) NumAttendees() int

func (*Event) NumGuests

func (e *Event) NumGuests() int

func (*Event) PictureDigest

func (e *Event) PictureDigest() []byte

func (*Event) StartDate

func (e *Event) StartDate() time.Time

func (*Event) Status

func (e *Event) Status() api.EventState

func (*Event) Timestamp

func (e *Event) Timestamp() int64

func (*Event) Title

func (e *Event) Title() string

type EventBuilder

type EventBuilder interface {
	SetAuthor(author *UserAccount) EventBuilder
	SetCreatedDate(date time.Time) EventBuilder
	SetStartDate(date time.Time) EventBuilder
	SetEndDate(date time.Time) EventBuilder
	SetDescription(desc string) EventBuilder
	ParticipantAdder() ParticipantAdder
	Build() (*Event, error)
}

type EventManager

type EventManager struct {
	// contains filtered or unexported fields
}

func (*EventManager) BuildEventsHistory

func (m *EventManager) BuildEventsHistory() error

func (*EventManager) BuildEventsTimeLine

func (m *EventManager) BuildEventsTimeLine() error

func (*EventManager) ChangeDeliveryState

func (m *EventManager) ChangeDeliveryState(userID int64, state api.InvitationStatus, event *Event) (*Participant, error)

Assumptions: - (1) User who performs this operation has permissions

Preconditions: - (1) Event is valid and persisted - (2) Event must have not started - (3) User must have received this invitation, i.e. user is in event participant list

func (*EventManager) ChangeEventPicture

func (m *EventManager) ChangeEventPicture(event *Event, picture []byte) error

Change event picture

Assumptions: - (1) Event exist and is persisted in DB - (2) User who performs this operation have permission

Preconditions - (1) Event is valid and persisted - (2) Event must have not started

func (*EventManager) ChangeParticipantResponse

func (m *EventManager) ChangeParticipantResponse(eventID int64, userID int64, response api.AttendanceResponse) (*Participant, error)

Change participant response to an event. Returns true if response changed, or false otherwise. For instance, if response is equal to old response, then it would return false.

Assumptions: - (1) User who performs this operation has permissions

Preconditions: - (1) Event is valid and persisted - (2) Event must have not started - (3) User must have received this invitation, i.e. user is in event participant list

func (*EventManager) ExtractNewParticipants

func (m *EventManager) ExtractNewParticipants(extractEvent *Event, baseEvent *Event) map[int64]*Participant

ExtractNewParticipants extracts participants from extractList that are not in baseList

func (*EventManager) GetEventForUser

func (m *EventManager) GetEventForUser(userID int64, eventID int64) (*Event, error)

func (*EventManager) GetEventsHistory

func (m *EventManager) GetEventsHistory(userID int64, start time.Time, end time.Time) ([]*Event, error)

func (*EventManager) GetRecentEvents

func (m *EventManager) GetRecentEvents(userID int64) ([]*Event, error)

TODO: Do not get all of the private events, but limit to a fixed number with pagination support.

func (*EventManager) LoadEvent

func (m *EventManager) LoadEvent(eventID int64) (*Event, error)

func (*EventManager) NewEvent

func (m *EventManager) NewEvent(author *UserAccount, createdDate time.Time, startDate time.Time, endDate time.Time,
	description string, participants []int64) (*Event, error)

func (*EventManager) NewEventModifier

func (m *EventManager) NewEventModifier(event *Event, ownerID int64) EventModifier

func (*EventManager) NewParticipantModifier

func (m *EventManager) NewParticipantModifier(p *Participant) ParticipantModifier

func (*EventManager) Observe

func (m *EventManager) Observe() observer.Stream

func (*EventManager) RemoveFromInbox

func (m *EventManager) RemoveFromInbox(userID int64, eventID int64)

RemoveFromInbox is a workaround method to enable server removing cancelled events from inbox after it has been sent to the client. This method will not be needed when an API to retrieve last changes is able.

func (*EventManager) SaveEvent

func (m *EventManager) SaveEvent(event *Event) error

* Save an event into database in order to let users request his events list * * Preconditions: * (1) event must have been initialised by model, this implies event object * is valid * (2) event must not be not persisted

type EventModifier

type EventModifier interface {
	SetModifiedDate(date time.Time) EventModifier
	SetStartDate(date time.Time) EventModifier
	SetEndDate(date time.Time) EventModifier
	SetDescription(desc string) EventModifier
	ParticipantAdder() ParticipantAdder
	SetCancelled(cancelled bool) EventModifier
	Build() (*Event, error)
}

type FBCredential

type FBCredential struct {
	FbId  string
	Token string
}

type Friend

type Friend struct {
	// contains filtered or unexported fields
}

func NewFriend

func NewFriend(id int64, name string, pictureDigest []byte) *Friend

func (*Friend) AsDTO

func (f *Friend) AsDTO() *api.FriendDTO

func (*Friend) Id

func (f *Friend) Id() int64

func (*Friend) Name

func (f *Friend) Name() string

func (*Friend) PictureDigest

func (f *Friend) PictureDigest() []byte

type FriendManager

type FriendManager struct {
	// contains filtered or unexported fields
}

func (*FriendManager) AddGroups

func (m *FriendManager) AddGroups(userID int64, groups []*Group) error

Adds friends groups to user 'userId'. If a group already exists it is updated.

func (*FriendManager) AreFriends

func (m *FriendManager) AreFriends(user1 int64, user2 int64) (bool, error)

func (*FriendManager) ConfirmFriendRequest

func (m *FriendManager) ConfirmFriendRequest(fromUser *UserAccount, toUser *UserAccount, accept bool) error

func (*FriendManager) CreateFriendRequest

func (m *FriendManager) CreateFriendRequest(fromUser *UserAccount, toUser *UserAccount) (*FriendRequest, error)

func (*FriendManager) DeleteGroup

func (m *FriendManager) DeleteGroup(userID int64, groupID int32) error

Remove group

func (*FriendManager) GetAllFriendRequests

func (m *FriendManager) GetAllFriendRequests(toUser int64) ([]*FriendRequest, error)

func (*FriendManager) GetAllFriends

func (self *FriendManager) GetAllFriends(userID int64) ([]*Friend, error)

func (*FriendManager) GetAllGroups

func (m *FriendManager) GetAllGroups(userID int64) ([]*Group, error)

func (*FriendManager) GetFacebookFriends

func (m *FriendManager) GetFacebookFriends(user *UserAccount) ([]*UserAccount, error)

GetFacebookFriends gets AreYouIN users that are friends of given user in Facebook

func (*FriendManager) GetNewFacebookFriends

func (m *FriendManager) GetNewFacebookFriends(user *UserAccount) ([]*UserAccount, error)

GetNewFacebookFriends gets AreYouIN users that are friends in Facebook but not in AreYouIN

func (*FriendManager) ImportFacebookFriends

func (m *FriendManager) ImportFacebookFriends(user *UserAccount, initialImport bool) ([]*UserAccount, error)

ImportFacebookFriends adds to user's list those AreYouIN users that are friends in Facebook but not in AreYouIN Returns the list of users that has been added by this operation

func (*FriendManager) IsFriend

func (m *FriendManager) IsFriend(user1 int64, user2 int64) (bool, error)

Since makeFriends() is bidirectional (adds the friend to user1 and user2). It can be assumed that if first user is friend of the second one, then second user must also have the first user in his/her friend list.

func (*FriendManager) MakeFriends

func (m *FriendManager) MakeFriends(user1 *UserAccount, user2 *UserAccount) error

func (*FriendManager) Observe

func (m *FriendManager) Observe() observer.Stream

func (*FriendManager) RenameGroup

func (m *FriendManager) RenameGroup(userID int64, groupID int32, newName string) error

Rename group

type FriendRequest

type FriendRequest struct {
	// contains filtered or unexported fields
}

func NewFriendRequest

func NewFriendRequest(toUser int64, fromUser int64, name string, email string) *FriendRequest

func (*FriendRequest) AsDTO

func (r *FriendRequest) AsDTO() *api.FriendRequestDTO

func (*FriendRequest) CreatedDate

func (r *FriendRequest) CreatedDate() int64

func (*FriendRequest) FromUser

func (r *FriendRequest) FromUser() int64

func (*FriendRequest) FromUserEmail

func (r *FriendRequest) FromUserEmail() string

func (*FriendRequest) FromUserName

func (r *FriendRequest) FromUserName() string

func (*FriendRequest) ToUser

func (r *FriendRequest) ToUser() int64

type Group

type Group struct {
	// contains filtered or unexported fields
}

func NewGroup

func NewGroup(id int32, name string, size int32) *Group

func (*Group) AsDTO

func (g *Group) AsDTO() *api.GroupDTO

func (*Group) Clone

func (g *Group) Clone() *Group

func (*Group) Id

func (g *Group) Id() int32

func (*Group) Members

func (g *Group) Members() []int64

func (*Group) Name

func (g *Group) Name() string

func (*Group) Size

func (g *Group) Size() int

type GroupBuilder

type GroupBuilder struct {
	// contains filtered or unexported fields
}

func NewGroupBuilder

func NewGroupBuilder() *GroupBuilder

func (*GroupBuilder) AddMember

func (b *GroupBuilder) AddMember(friendId int64) *GroupBuilder

func (*GroupBuilder) Build

func (b *GroupBuilder) Build() *Group

func (*GroupBuilder) SetId

func (b *GroupBuilder) SetId(id int32) *GroupBuilder

func (*GroupBuilder) SetName

func (b *GroupBuilder) SetName(name string) *GroupBuilder

type IIDToken

type IIDToken struct {
	// contains filtered or unexported fields
}

func NewIIDToken

func NewIIDToken(token string, version int, platform string) *IIDToken

func (IIDToken) AsDTO

func (t IIDToken) AsDTO() *api.IIDTokenDTO

func (*IIDToken) Platform

func (t *IIDToken) Platform() string

func (*IIDToken) Token

func (t *IIDToken) Token() string

func (*IIDToken) Version

func (t *IIDToken) Version() int

type ModelsMap

type ModelsMap struct {
	// contains filtered or unexported fields
}

func (*ModelsMap) Get

func (sm *ModelsMap) Get(key string) (v *AyiModel, ok bool)

func (*ModelsMap) Keys

func (sm *ModelsMap) Keys() (keys []string)

func (*ModelsMap) Len

func (sm *ModelsMap) Len() int

func (*ModelsMap) Put

func (sm *ModelsMap) Put(key string, model *AyiModel)

func (*ModelsMap) Remove

func (sm *ModelsMap) Remove(key string)

type Participant

type Participant struct {
	// contains filtered or unexported fields
}

func NewParticipant

func NewParticipant(id int64, name string, response api.AttendanceResponse,
	status api.InvitationStatus) *Participant

func (*Participant) AsDTO

func (p *Participant) AsDTO() *api.ParticipantDTO

func (*Participant) Clone

func (p *Participant) Clone() *Participant

func (*Participant) Equal

func (p *Participant) Equal(other *Participant) bool

func (*Participant) EventID

func (p *Participant) EventID() int64

func (*Participant) Id

func (p *Participant) Id() int64

func (*Participant) InvitationStatus

func (p *Participant) InvitationStatus() api.InvitationStatus

func (*Participant) Name

func (p *Participant) Name() string

func (*Participant) Response

func (p *Participant) Response() api.AttendanceResponse

type ParticipantAdder

type ParticipantAdder interface {
	AddUserAccount(u *UserAccount) ParticipantAdder
	AddFriend(f *Friend) ParticipantAdder
	AddParticipant(p *Participant) ParticipantAdder
	AddUserID(UID int64) ParticipantAdder
}

type ParticipantList

type ParticipantList struct {
	// contains filtered or unexported fields
}

func (*ParticipantList) AsSlice

func (l *ParticipantList) AsSlice() []*Participant

func (*ParticipantList) Clone

func (l *ParticipantList) Clone() *ParticipantList

func (*ParticipantList) Equal

func (l *ParticipantList) Equal(other *ParticipantList) bool

func (*ParticipantList) Get

func (l *ParticipantList) Get(id int64) (*Participant, bool)

func (*ParticipantList) Ids

func (l *ParticipantList) Ids() []int64

func (*ParticipantList) NumAttendees

func (l *ParticipantList) NumAttendees() int

func (*ParticipantList) NumGuests

func (l *ParticipantList) NumGuests() int

type ParticipantModifier

type ParticipantModifier interface {
	SetResponse(resp api.AttendanceResponse) ParticipantModifier
	SetInvitationStatus(status api.InvitationStatus) ParticipantModifier
	Build() (*Participant, error)
}

type Picture

type Picture struct {
	RawData []byte
	Digest  []byte
}

func (*Picture) AsDTO

func (p *Picture) AsDTO() *api.PictureDTO

type Signal

type Signal struct {
	Type SignalType
	Data map[string]interface{}
}

type SignalType

type SignalType int
const (

	// Event published
	SignalNewEvent SignalType = iota

	// Event cancelled
	SignalEventCancelled SignalType = iota

	// Event modified (picture, start date, ...)
	SignalEventInfoChanged SignalType = iota

	// Event participant list changed (added or removed participants)
	SignalEventParticipantsInvited SignalType = iota

	// Participant changed (response, invitationStatus)
	SignalParticipantChanged SignalType = iota

	// New registered user
	SignalNewUserAccount SignalType = iota

	// Friends imported
	SignalNewFriendsImported SignalType = iota

	// Friend request sent
	SignalNewFriendRequest SignalType = iota

	// Friend request accepted
	SignalFriendRequestAccepted SignalType = iota

	// Friend request cancelled
	SignalFriendRequestCancelled SignalType = iota
)

type UserAccount

type UserAccount struct {
	// contains filtered or unexported fields
}

func NewUserAccount

func NewUserAccount(name string, email string, password string, phone string,
	fbId string, fbToken string) (*UserAccount, error)

func (*UserAccount) AsDTO

func (u *UserAccount) AsDTO() *api.UserDTO

func (*UserAccount) AsFriend

func (u *UserAccount) AsFriend() *Friend

func (*UserAccount) AsParticipant

func (u *UserAccount) AsParticipant() *Participant

func (*UserAccount) AuthToken

func (u *UserAccount) AuthToken() string

func (*UserAccount) Clone

func (u *UserAccount) Clone() *UserAccount

func (*UserAccount) CreatedDate

func (u *UserAccount) CreatedDate() int64

func (*UserAccount) Email

func (u *UserAccount) Email() string

func (*UserAccount) FbId

func (u *UserAccount) FbId() string

func (*UserAccount) FbToken

func (u *UserAccount) FbToken() string

func (*UserAccount) HasFacebook

func (u *UserAccount) HasFacebook() bool

func (*UserAccount) Id

func (u *UserAccount) Id() int64

func (*UserAccount) IsZero

func (u *UserAccount) IsZero() bool

func (*UserAccount) Name

func (u *UserAccount) Name() string

func (*UserAccount) PictureDigest

func (u *UserAccount) PictureDigest() []byte

func (*UserAccount) PushToken

func (u *UserAccount) PushToken() IIDToken

type UserEvents

type UserEvents struct {
	// contains filtered or unexported fields
}

func (*UserEvents) Clear

func (u *UserEvents) Clear()

func (*UserEvents) FindAll

func (u *UserEvents) FindAll(userID int64) []int64

func (*UserEvents) Insert

func (u *UserEvents) Insert(userID int64, eventID int64)

func (*UserEvents) Len

func (u *UserEvents) Len() int

func (*UserEvents) Remove

func (u *UserEvents) Remove(userID int64, eventID int64)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL