feat(activitylog): finalize initial activitylog service

Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
jkoberg
2024-06-07 12:10:39 +02:00
parent bd7abeb9d7
commit e05b244f6e
6 changed files with 46 additions and 30 deletions
+14 -1
View File
@@ -1,2 +1,15 @@
# Activitylog Service
It is mandatory to provide a README.md file for each service. This file should contain a brief description of the service and how to use it.
The `activitylog` service is responsible for storing events (activities) per resource.
## The Log Service Ecosystem
Log services like the `activitylog`, `userlog`, `clientlog` and `sse` are responsible for composing notifications for a certain audience.
- The `userlog` service translates and adjusts messages to be human readable.
- The `clientlog` service composes machine readable messages, so clients can act without the need to query the server.
- The `sse` service is only responsible for sending these messages. It does not care about their form or language.
- The `activitylog` service stores events per resource. These can be retrieved to show item activities
## Activitylog Store
The `activitylog` stores activities for each resource. It works in conjunction with the `eventhistory` service to keep the data it needs to store to a minimum.
+28 -27
View File
@@ -34,7 +34,7 @@ type ActivitylogService struct {
gws pool.Selectable[gateway.GatewayAPIClient]
}
// New is what you need to implement.
// New creates a new ActivitylogService
func New(opts ...Option) (*ActivitylogService, error) {
o := &Options{}
for _, opt := range opts {
@@ -109,7 +109,7 @@ func (a *ActivitylogService) Run() error {
return nil
}
// AddActivity addds the activity to the given resource and all its parents
// AddActivity adds the activity to the given resource and all its parents
func (a *ActivitylogService) AddActivity(initRef *provider.Reference, eventID string, timestamp time.Time) error {
gwc, err := a.gws.Next()
if err != nil {
@@ -126,31 +126,7 @@ func (a *ActivitylogService) AddActivity(initRef *provider.Reference, eventID st
})
}
// Activities returns the activities for the given reference
func (a *ActivitylogService) Activities(ref *provider.Reference) ([]Activity, error) {
resourceID, err := storagespace.FormatReference(ref)
if err != nil {
return nil, fmt.Errorf("could not format reference: %w", err)
}
records, err := a.store.Read(resourceID)
if err != nil && err != microstore.ErrNotFound {
return nil, fmt.Errorf("could not read activities: %w", err)
}
if len(records) == 0 {
return []Activity{}, nil
}
var activities []Activity
if err := json.Unmarshal(records[0].Value, &activities); err != nil {
return nil, fmt.Errorf("could not unmarshal activities: %w", err)
}
return activities, nil
}
// AddActivityTrashed adds the activity to trashed item
// AddActivityTrashed adds the activity to given trashed resource and all its former parents
func (a *ActivitylogService) AddActivityTrashed(resourceID *provider.ResourceId, reference *provider.Reference, eventID string, timestamp time.Time) error {
gwc, err := a.gws.Next()
if err != nil {
@@ -178,6 +154,27 @@ func (a *ActivitylogService) AddActivityTrashed(resourceID *provider.ResourceId,
})
}
// Activities returns the activities for the given resource
func (a *ActivitylogService) Activities(rid *provider.ResourceId) ([]Activity, error) {
resourceID := storagespace.FormatResourceID(*rid)
records, err := a.store.Read(resourceID)
if err != nil && err != microstore.ErrNotFound {
return nil, fmt.Errorf("could not read activities: %w", err)
}
if len(records) == 0 {
return []Activity{}, nil
}
var activities []Activity
if err := json.Unmarshal(records[0].Value, &activities); err != nil {
return nil, fmt.Errorf("could not unmarshal activities: %w", err)
}
return activities, nil
}
// note: getResource is abstracted to allow unit testing, in general this will just be utils.GetResource
func (a *ActivitylogService) addActivity(initRef *provider.Reference, eventID string, timestamp time.Time, getResource func(*provider.Reference) (*provider.ResourceInfo, error)) error {
var (
@@ -206,6 +203,10 @@ func (a *ActivitylogService) addActivity(initRef *provider.Reference, eventID st
}
func (a *ActivitylogService) storeActivity(rid *provider.ResourceId, eventID string, depth int, timestamp time.Time) error {
if rid == nil {
return errors.New("resource id is required")
}
resourceID := storagespace.FormatResourceID(*rid)
records, err := a.store.Read(resourceID)
@@ -136,7 +136,7 @@ func TestAddActivity(t *testing.T) {
}
for id, acts := range tc.Expected {
activities, err := alog.Activities(reference(id))
activities, err := alog.Activities(resourceID(id))
require.NoError(t, err, tc.Name+":"+id)
require.ElementsMatch(t, acts, activities, tc.Name+":"+id)
}