mirror of
https://github.com/diamondburned/cchat.git
synced 2025-07-07 03:17:23 +00:00
This commit removes all stop callbacks in ContainerMethods. The intention is to have backends disconnect callbacks when the context is cancelled, rather than when the stop function is called. This helps get rid of countless race condition flaws caused by the duration between the context being cancelled on one thread and the stop callback being set in another, causing the handlers to not disconnect.
156 lines
5.1 KiB
Go
156 lines
5.1 KiB
Go
package repository
|
|
|
|
import (
|
|
"encoding/gob"
|
|
"strings"
|
|
)
|
|
|
|
func init() {
|
|
gob.Register(ContainerMethod{})
|
|
gob.Register(AsserterMethod{})
|
|
gob.Register(GetterMethod{})
|
|
gob.Register(SetterMethod{})
|
|
gob.Register(IOMethod{})
|
|
}
|
|
|
|
type Interface struct {
|
|
Comment Comment
|
|
Name string
|
|
Embeds []EmbeddedInterface
|
|
Methods []Method // actual methods
|
|
}
|
|
|
|
type EmbeddedInterface struct {
|
|
Comment Comment
|
|
InterfaceName string
|
|
}
|
|
|
|
// IsContainer returns true if the interface is a frontend container interface,
|
|
// that is when its name has "Container" at the end.
|
|
func (i Interface) IsContainer() bool {
|
|
return strings.HasSuffix(i.Name, "Container")
|
|
}
|
|
|
|
type Method interface {
|
|
UnderlyingName() string
|
|
UnderlyingComment() Comment
|
|
internalMethod()
|
|
}
|
|
|
|
type method struct {
|
|
Comment Comment
|
|
Name string
|
|
}
|
|
|
|
func (m method) UnderlyingName() string { return m.Name }
|
|
func (m method) UnderlyingComment() Comment { return m.Comment }
|
|
func (m method) internalMethod() {}
|
|
|
|
// GetterMethod is a method that returns a regular value. These methods must not
|
|
// do any IO. An example of one would be ID() returning ID.
|
|
type GetterMethod struct {
|
|
method
|
|
|
|
// Parameters is the list of parameters in the function.
|
|
Parameters []NamedType
|
|
// Returns is the list of named types returned from the function.
|
|
Returns []NamedType
|
|
// ErrorType is non-empty if the function returns an error at the end of
|
|
// returns. For the most part, this field should be "error" if that is the
|
|
// case, but some methods may choose to extend the error base type.
|
|
ErrorType string
|
|
}
|
|
|
|
// ReturnError returns true if the method can error out.
|
|
func (m GetterMethod) ReturnError() bool {
|
|
return m.ErrorType != ""
|
|
}
|
|
|
|
// SetterMethod is a method that sets values. These methods must not do IO, and
|
|
// they have to be non-blocking. They're used only for containers. Actual setter
|
|
// methods implemented by the backend belongs to IOMethods.
|
|
//
|
|
// Clients should always keep track of the values given to setters and free them
|
|
// once the setters are called again with new values.
|
|
type SetterMethod struct {
|
|
method
|
|
|
|
// Parameters is the list of parameters in the function. These parameters
|
|
// should be the parameters to set.
|
|
Parameters []NamedType
|
|
// ErrorType is non-empty if the function returns an error at the end of
|
|
// returns. An error may be returned from the backend if the input is
|
|
// invalid, but it must not do IO. Frontend setters must never error.
|
|
ErrorType string
|
|
}
|
|
|
|
// IOMethod is a regular method that can do IO and thus is blocking. These
|
|
// methods usually always return errors. IOMethods must always have means of
|
|
// cancelling them in the API, but implementations don't have to use it; as
|
|
// such, the user should always have a timeout to gracefully wait.
|
|
type IOMethod struct {
|
|
method
|
|
|
|
// Parameters is the list of parameters in the function.
|
|
Parameters []NamedType
|
|
// ReturnValue is the return value in the function.
|
|
ReturnValue NamedType
|
|
// ErrorType is non-empty if the function returns an error at the end of
|
|
// returns. For the most part, this field should be "error" if that is the
|
|
// case, but some methods may choose to extend the error base type.
|
|
ErrorType string
|
|
// Disposer indicates that this method signals the disposal of the interface
|
|
// that implements it. This is used similarly to stop functions, except all
|
|
// disposer functions can be synchronous, and the frontend should handle
|
|
// indicating such. The frontend can also ignore the result and run the
|
|
// method in a dangling goroutine, but it must gracefully wait for it to be
|
|
// done on exit.
|
|
//
|
|
// Similarly to the stop function, the instance that the disposer method belongs
|
|
// to will also be considered invalid and should be freed once the function
|
|
// returns regardless of the error.
|
|
Disposer bool
|
|
}
|
|
|
|
// ReturnError returns true if the method can error out.
|
|
func (m IOMethod) ReturnError() bool {
|
|
return m.ErrorType != ""
|
|
}
|
|
|
|
// ContainerMethod is a method that uses a Container. These methods can do IO,
|
|
// and they must always take in a context and return an error. The context is
|
|
// used for both stopping an ongoing IO operation and disconnecting background
|
|
// handlers for the container.
|
|
type ContainerMethod struct {
|
|
method
|
|
|
|
// ContainerType is the name of the container interface. The name will
|
|
// almost always have "Container" as its suffix.
|
|
ContainerType string
|
|
}
|
|
|
|
// Qual returns what TypeQual returns with m.ContainerType.
|
|
func (m ContainerMethod) Qual() (path, name string) {
|
|
return TypeQual(m.ContainerType)
|
|
}
|
|
|
|
// AsserterMethod is a method that allows the parent interface to extend itself
|
|
// into children interfaces. These methods must not do IO.
|
|
type AsserterMethod struct {
|
|
// ChildType is the children type that is returned.
|
|
ChildType string
|
|
}
|
|
|
|
func (m AsserterMethod) internalMethod() {}
|
|
func (m AsserterMethod) UnderlyingComment() Comment { return Comment{} }
|
|
|
|
// UnderlyingName returns the name of the method.
|
|
func (m AsserterMethod) UnderlyingName() string {
|
|
return "As" + m.ChildType
|
|
}
|
|
|
|
// Qual returns what TypeQual returns with m.ChildType.
|
|
func (m AsserterMethod) Qual() (path, name string) {
|
|
return TypeQual(m.ChildType)
|
|
}
|