Documentation
¶
Overview ¶
Package appengine is the AppEngine API (docs/DESIGN.md §3.7, ROADMAP §8.2): the operator/application surface for device status, interface data queries, server-owned publishing, groups, and the live event socket. It is wire-shaped to upstream astarte_appengine_api so astartectl and applications work unmodified, reading through the store and writing server-owned values through the engine.
Index ¶
- Constants
- Variables
- type API
- type DevicePage
- type DevicePatch
- type DeviceStatus
- type FieldErrors
- type QueryOpts
- type Sample
- type ServerData
- type Service
- func (s *Service) AddGroupDevice(ctx context.Context, realm, name, deviceID string) error
- func (s *Service) CreateGroup(ctx context.Context, realm, name string, devices []string) error
- func (s *Service) DevicesStats(ctx context.Context, realm string) (total, connected int64, err error)
- func (s *Service) GetData(ctx context.Context, realm, deviceID, ifaceName, path string, opts QueryOpts) (any, error)
- func (s *Service) GetDataByAlias(ctx context.Context, realm, alias, ifaceName, path string, opts QueryOpts) (any, error)
- func (s *Service) GetDataInGroup(ctx context.Context, realm, groupName, deviceID, ifaceName, path string, ...) (any, error)
- func (s *Service) GetDevice(ctx context.Context, realm, deviceID string) (*DeviceStatus, error)
- func (s *Service) GetDeviceByAlias(ctx context.Context, realm, alias string) (*DeviceStatus, error)
- func (s *Service) GetGroup(ctx context.Context, realm, name string) error
- func (s *Service) GetGroupDevice(ctx context.Context, realm, groupName, deviceID string) (*DeviceStatus, error)
- func (s *Service) ListDevices(ctx context.Context, realm string, after string, limit int, details bool) (*DevicePage, error)
- func (s *Service) ListGroupDevices(ctx context.Context, realm, name string, details bool, fromToken string, ...) (*DevicePage, error)
- func (s *Service) ListGroups(ctx context.Context, realm string) ([]string, error)
- func (s *Service) ListInterfaces(ctx context.Context, realm, deviceID string) ([]string, error)
- func (s *Service) ListInterfacesByAlias(ctx context.Context, realm, alias string) ([]string, error)
- func (s *Service) ListInterfacesInGroup(ctx context.Context, realm, groupName, deviceID string) ([]string, error)
- func (s *Service) PatchDevice(ctx context.Context, realm, deviceID string, p DevicePatch) (*DeviceStatus, error)
- func (s *Service) PatchDeviceByAlias(ctx context.Context, realm, alias string, p DevicePatch) (*DeviceStatus, error)
- func (s *Service) PatchGroupDevice(ctx context.Context, realm, groupName, deviceID string, p DevicePatch) (*DeviceStatus, error)
- func (s *Service) PublishData(ctx context.Context, realm, deviceID, ifaceName, path string, ...) error
- func (s *Service) PublishDataByAlias(ctx context.Context, realm, alias, ifaceName, path string, ...) error
- func (s *Service) PublishDataInGroup(ctx context.Context, realm, groupName, deviceID, ifaceName, path string, ...) error
- func (s *Service) RemoveGroupDevice(ctx context.Context, realm, name, deviceID string) error
- func (s *Service) UnsetProperty(ctx context.Context, realm, deviceID, ifaceName, path string) error
- func (s *Service) UnsetPropertyByAlias(ctx context.Context, realm, alias, ifaceName, path string) error
- func (s *Service) UnsetPropertyInGroup(ctx context.Context, realm, groupName, deviceID, ifaceName, path string) error
- type Tabular
Constants ¶
const DefaultDeviceLimit = 100
DefaultDeviceLimit is the device-list page size when the caller gives none.
Variables ¶
var ( ErrInvalidAlias = errors.New("Invalid alias") //nolint:staticcheck // ST1005: detail strings are upstream astarte_appengine_api 1.2.2 wire text ErrAliasAlreadyInUse = errors.New("Alias already in use") //nolint:staticcheck // ST1005: upstream wire text ErrAliasTagNotFound = errors.New("Alias tag not found") //nolint:staticcheck // ST1005: upstream wire text ErrInvalidAttributes = errors.New("Invalid attributes") //nolint:staticcheck // ST1005: upstream wire text ErrAttributeKeyNotFound = errors.New("Attribute key not found") //nolint:staticcheck // ST1005: upstream wire text )
Device-PATCH error taxonomy, frozen to upstream astarte_appengine_api 1.2.2 (FallbackController + ErrorView): the detail strings are what astartectl and the dashboard match on.
var ErrDeviceAlreadyInGroup = fmt.Errorf("Device already in group: %w", store.ErrAlreadyExists) //nolint:staticcheck // ST1005: upstream wire text
ErrDeviceAlreadyInGroup marks re-adding an existing member (maps to 409 "Device already in group"); it too satisfies store.ErrAlreadyExists.
var ErrGroupAlreadyExists = fmt.Errorf("Group already exists: %w", store.ErrAlreadyExists) //nolint:staticcheck // ST1005: upstream wire text
ErrGroupAlreadyExists marks a duplicate group name (maps to 409 "Group already exists"); it also satisfies store.ErrAlreadyExists so generic duplicate handling keeps working.
var ErrGroupNotFound = errors.New("Group not found") //nolint:staticcheck // ST1005: upstream wire text
ErrGroupNotFound marks a missing group (maps to 404 "Group not found").
var ErrPathNotFound = errors.New("appengine: path not found")
ErrPathNotFound marks an object-aggregated series whose concrete path holds no rows at all (upstream answers 404 "Path not found"; the interface root renders {} instead).
var ErrValidation = errors.New("appengine: validation failed")
ErrValidation wraps a well-formed request that violates a rule (maps to 422).
Functions ¶
This section is empty.
Types ¶
type API ¶
type API struct {
// contains filtered or unexported fields
}
API is the /appengine/v1 HTTP surface (docs/ROADMAP.md §8.2 file 7.8), guarded by a realm JWT carrying a_aea.
type DevicePage ¶ added in v0.2.0
type DevicePage struct {
IDs []string
Statuses []*DeviceStatus
Next string
}
DevicePage is one device-list page: IDs, or full statuses when details was requested. Next is the next-page cursor ("" at the end).
type DevicePatch ¶
type DevicePatch struct {
Aliases map[string]*string
Attributes map[string]*string
CredentialsInhibited *bool
}
DevicePatch carries the JSON-merge-style PATCH fields (upstream DevicePatch): a nil pointer leaves a field unchanged, a present map patches aliases/attributes (a nil map value removes that key).
type DeviceStatus ¶
type DeviceStatus struct {
ID string `json:"id"`
Connected bool `json:"connected"`
Introspection map[string]introspectionEntry `json:"introspection"`
Aliases map[string]string `json:"aliases"`
Attributes map[string]string `json:"attributes"`
Groups []string `json:"groups"`
CredentialsInhibited bool `json:"credentials_inhibited"`
TotalReceivedMsgs int64 `json:"total_received_msgs"`
TotalReceivedBytes int64 `json:"total_received_bytes"`
FirstRegistration *time.Time `json:"first_registration"`
FirstCredentialsReq *time.Time `json:"first_credentials_request"`
LastConnection *time.Time `json:"last_connection"`
LastDisconnection *time.Time `json:"last_disconnection"`
LastSeenIP string `json:"last_seen_ip,omitempty"`
PreviousInterfaces map[string]introspectionEntry `json:"previous_interfaces,omitempty"`
}
DeviceStatus is the AppEngine device status body (upstream DeviceStatusView): a JSON-friendly projection of a devices row.
type FieldErrors ¶ added in v0.2.0
FieldErrors carries per-field validation failures rendered as the Phoenix-changeset envelope {"errors":{"<field>":["<message>",...]}} (422).
func (FieldErrors) Error ¶ added in v0.2.0
func (fe FieldErrors) Error() string
type QueryOpts ¶
type QueryOpts struct {
Since *time.Time
SinceAfter *time.Time
To *time.Time
Limit int
Descending bool
DownsamplePoints int
Format string
DownsampleKey string
RetrieveMetadata bool
AllowBigIntegers *bool
AllowSafeBigIntegers *bool
}
QueryOpts are the datastream query parameters (upstream since/since_after/ to/limit/downsample_to plus the rendering options). The zero value reads the whole series ascending and renders structured.
DownsamplePoints is the request's `downsample_to` value — a target *point count*, which is upstream's semantics. The bucket width is derived locally inside datastreamData once the series' own time span is known.
Format is one of structured/table/disjoint_tables ("structured" when the request omitted it). AllowBigIntegers/AllowSafeBigIntegers are nil when the request did not name them; they affect object-document rendering only.
type ServerData ¶
type ServerData interface {
PublishServerValue(ctx context.Context, realm string, id deviceid.ID, iface, path string, value json.RawMessage, ts *time.Time) error
UnsetServerProperty(ctx context.Context, realm string, id deviceid.ID, iface, path string) error
}
ServerData is the engine port for server-owned writes (docs/ROADMAP.md §8.2 file 7.7). *engine.Engine satisfies it; tests substitute a fake.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service implements the AppEngine business logic over the store and engine.
func NewService ¶
NewService builds the service. sd may be nil (read-only deployments); log defaults to slog.Default().
func (*Service) AddGroupDevice ¶
AddGroupDevice adds a device to a group.
func (*Service) CreateGroup ¶
CreateGroup creates a group with its initial device membership (upstream POST /groups requires a non-empty device list). Blank-name and empty-device rejections live at the handler level as field errors; here every listed id must parse AND name an existing device row — a single failure rejects the whole body with the upstream changeset message, before any row is created.
func (*Service) DevicesStats ¶ added in v0.2.0
func (s *Service) DevicesStats(ctx context.Context, realm string) (total, connected int64, err error)
DevicesStats counts the realm's devices (upstream GET /stats/devices).
func (*Service) GetData ¶
func (s *Service) GetData(ctx context.Context, realm, deviceID, ifaceName, path string, opts QueryOpts) (any, error)
GetData reads an interface endpoint (upstream GET .../interfaces/{iface} [/{path}]), dispatching on the interface type: a datastream series (with the query options) or a properties snapshot.
func (*Service) GetDataByAlias ¶ added in v0.2.0
func (s *Service) GetDataByAlias(ctx context.Context, realm, alias, ifaceName, path string, opts QueryOpts) (any, error)
GetDataByAlias reads an interface endpoint on an alias-addressed device (upstream GET /devices-by-alias/{alias}/interfaces/{iface}[/{path}]).
func (*Service) GetDataInGroup ¶ added in v0.2.0
func (s *Service) GetDataInGroup(ctx context.Context, realm, groupName, deviceID, ifaceName, path string, opts QueryOpts) (any, error)
GetDataInGroup reads an interface endpoint on a group member (upstream GET /groups/{group}/devices/{device}/interfaces/{iface}[/{path}]).
func (*Service) GetDeviceByAlias ¶
GetDeviceByAlias returns the status of the device owning an alias (upstream GET /devices-by-alias/{alias}).
func (*Service) GetGroup ¶ added in v0.2.0
GetGroup resolves one group by name (upstream GET /groups/{group}).
func (*Service) GetGroupDevice ¶ added in v0.2.0
func (s *Service) GetGroupDevice(ctx context.Context, realm, groupName, deviceID string) (*DeviceStatus, error)
GetGroupDevice returns one member device's status (upstream GET /groups/{group}/devices/{device}).
func (*Service) ListDevices ¶
func (s *Service) ListDevices(ctx context.Context, realm string, after string, limit int, details bool) (*DevicePage, error)
ListDevices returns one page of devices (upstream GET /devices). after is the cursor (exclusive); limit <= 0 selects DefaultDeviceLimit; details switches the page from bare IDs to full status objects (the dashboard's device list).
func (*Service) ListGroupDevices ¶
func (s *Service) ListGroupDevices(ctx context.Context, realm, name string, details bool, fromToken string, limit int) (*DevicePage, error)
ListGroupDevices returns one page of the devices in a group — bare IDs, or full status objects with details (the dashboard's group page). The bare listing paginates with an OFFSET cursor carried inside a UUID-v1-format from_token (upstream's own tokens are insertion-time v1 uuids; any well-formed v1 string is accepted); details stays unpaginated.
func (*Service) ListGroups ¶
ListGroups returns the realm's group names.
func (*Service) ListInterfaces ¶ added in v0.2.0
ListInterfaces returns a device's introspection interface names, sorted ascending (upstream GET .../devices/{d}/interfaces).
func (*Service) ListInterfacesByAlias ¶ added in v0.2.0
ListInterfacesByAlias is ListInterfaces addressed by alias.
func (*Service) ListInterfacesInGroup ¶ added in v0.2.0
func (s *Service) ListInterfacesInGroup(ctx context.Context, realm, groupName, deviceID string) ([]string, error)
ListInterfacesInGroup is ListInterfaces inside a group (membership gate first).
func (*Service) PatchDevice ¶
func (s *Service) PatchDevice(ctx context.Context, realm, deviceID string, p DevicePatch) (*DeviceStatus, error)
PatchDevice applies a device patch (upstream PATCH /devices/{id}).
func (*Service) PatchDeviceByAlias ¶ added in v0.2.0
func (s *Service) PatchDeviceByAlias(ctx context.Context, realm, alias string, p DevicePatch) (*DeviceStatus, error)
PatchDeviceByAlias applies a device patch addressed by alias (upstream PATCH /devices-by-alias/{alias}). Unknown alias behaves like GetDeviceByAlias.
func (*Service) PatchGroupDevice ¶ added in v0.2.0
func (s *Service) PatchGroupDevice(ctx context.Context, realm, groupName, deviceID string, p DevicePatch) (*DeviceStatus, error)
PatchGroupDevice applies a device patch inside a group (upstream PATCH /groups/{group}/devices/{device}). Unknown group → ErrGroupNotFound; non-member device behaves like an unknown device.
func (*Service) PublishData ¶
func (s *Service) PublishData(ctx context.Context, realm, deviceID, ifaceName, path string, value json.RawMessage, ts *time.Time) error
PublishData writes a server-owned value (upstream PUT/POST .../interfaces/{iface}/{path}) through the engine. value is the unwrapped "data" JSON; ts is the optional explicit timestamp.
func (*Service) PublishDataByAlias ¶ added in v0.2.0
func (s *Service) PublishDataByAlias(ctx context.Context, realm, alias, ifaceName, path string, value json.RawMessage, ts *time.Time) error
PublishDataByAlias publishes through an alias address; the resolution gates access and carries the real device ID to the engine write.
func (*Service) PublishDataInGroup ¶ added in v0.2.0
func (s *Service) PublishDataInGroup(ctx context.Context, realm, groupName, deviceID, ifaceName, path string, value json.RawMessage, ts *time.Time) error
PublishDataInGroup publishes through a group address.
func (*Service) RemoveGroupDevice ¶
RemoveGroupDevice removes a device from a group.
func (*Service) UnsetProperty ¶
UnsetProperty unsets a server-owned property (upstream DELETE .../interfaces/{iface}/{path}).
Directories
¶
| Path | Synopsis |
|---|---|
|
Package channels implements the upstream Phoenix Channels V2 wire protocol served at /appengine/v1/socket/websocket.
|
Package channels implements the upstream Phoenix Channels V2 wire protocol served at /appengine/v1/socket/websocket. |
|
Package stream is the AppEngine live event socket (docs/DESIGN.md §3.7, §1.1 deviation; ROADMAP §8.2 file 7.9): a WebSocket (with an SSE fallback) at /astrate/v1/{realm}/socket fed by the engine's in-process fan-out bus.
|
Package stream is the AppEngine live event socket (docs/DESIGN.md §3.7, §1.1 deviation; ROADMAP §8.2 file 7.9): a WebSocket (with an SSE fallback) at /astrate/v1/{realm}/socket fed by the engine's in-process fan-out bus. |