mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-05-05 11:00:12 -05:00
feat(activitylog): finalize initial activitylog service
Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user