Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 8 additions & 18 deletions docs/content/2.concepts/1.how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,26 +56,16 @@ Sources should respect `cap` to keep memory bounded — `RelatedActivityLogSourc

## Type taxonomy

::callout{icon="i-lucide-alert-triangle" color="warning"}
**Two distinct "type" axes exist. Do not confuse them.**
The **entry-type** axis (`$entry->type`) and the **source-priority config** axis (`source_priorities` keys) align one-to-one:

The **entry-type** axis (`$entry->type`) has **3 values today**:
| Source | `$entry->type` | `source_priorities` key |
| -------------------------- | ---------------------- | ------------------------ |
| `ActivityLogSource` | `activity_log` | `activity_log` |
| `RelatedActivityLogSource` | `related_activity_log` | `related_activity_log` |
| `RelatedModelSource` | `related_model` | `related_model` |
| `CustomEventSource` | `custom` | `custom` |

- `activity_log`
- `related_model`
- `custom`

The **source-priority config** axis (`source_priorities` config keys) has **4 keys**:

- `activity_log`
- `related_activity_log`
- `related_model`
- `custom`

Critically: RelatedActivityLogSource emits entries with `type='activity_log'` (**not** `'related_activity_log'`). Filtering with `->ofType(['related_activity_log'])` will never match anything. To distinguish own-log entries from related-log entries today, inspect `$entry->relatedModel` (it's `null` for `ActivityLogSource` entries and an Eloquent model for `RelatedActivityLogSource` entries) after calling `->get()` — there is no builder-level filter for source-of-origin.

See [/troubleshooting](/troubleshooting) ("Type filter doesn't match anything") and [issue #11](https://github.com/relaticle/activity-log/issues/11).
::
To match both spatie-log sources in a filter, pass both keys: `->ofType(['activity_log', 'related_activity_log'])`. The built-in `ActivityLogRenderer` is auto-registered for both types, so diff rendering works for own-log and related-log entries without extra wiring.

## Source priorities

Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.essentials/1.sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ For each named relation, the source loads the related rows, then queries `activi
::

::callout{icon="i-lucide-info" color="info"}
Entries from this source carry `type='activity_log'`, **not** `'related_activity_log'`. The `related_activity_log` key only exists in `config('activity-log.source_priorities')` for priority configuration. See the type taxonomy in [/concepts/how-it-works](/concepts/how-it-works#type-taxonomy).
Entries from this source carry `type='related_activity_log'` and dedup-collide with the matching `RelatedModelSource` event when both fire at the same second. The built-in `ActivityLogRenderer` is auto-registered for both `activity_log` and `related_activity_log`, so spatie diffs render automatically for related-model logs too.
::

## `fromRelation(string $relation, Closure $configure)`
Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.essentials/2.filament-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ Each filter mutates the underlying `Relaticle\ActivityLog\Timeline\TimelineBuild
A `resetFilters()` Livewire action is wired to the clear button — it nulls all three properties and rewinds `visibleCount` to `perPage`.

::callout{icon="i-lucide-info" color="info"}
The `typeFilter` value is matched against `$entry->type`, so only the three real entry-type values resolve (`activity_log`, `related_model`, `custom`). Filtering by `'related_activity_log'` matches nothing — see the type taxonomy in [/concepts/how-it-works](/concepts/how-it-works#type-taxonomy).
The `typeFilter` value is matched against `$entry->type`. Built-in types: `activity_log`, `related_activity_log`, `related_model`, `custom`. See the type taxonomy in [/concepts/how-it-works](/concepts/how-it-works#type-taxonomy).
::

For programmatic equivalents — pre-applying filters from PHP rather than the URL — see [/essentials/refining-the-timeline](/essentials/refining-the-timeline).
4 changes: 2 additions & 2 deletions docs/content/3.essentials/3.refining-the-timeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ $record->timeline()

Type and event filters are mirrored onto every source's `Window` so sources can push them into SQL where possible. The builder also re-applies them post-yield as a safety net, so a source that ignores the `Window` filters still produces correct output.

::callout{icon="i-lucide-alert-triangle" color="warning"}
**There are only three entry types today: `activity_log`, `related_model`, `custom`.** Entries from `RelatedActivityLogSource` carry `type='activity_log'` — calling `->ofType(['related_activity_log'])` will silently match nothing. See the [type taxonomy](/concepts/how-it-works#type-taxonomy) for the full breakdown.
::callout{icon="i-lucide-info" color="info"}
**Built-in entry types: `activity_log`, `related_activity_log`, `related_model`, `custom`.** `ActivityLogSource` emits `activity_log`; `RelatedActivityLogSource` emits `related_activity_log`. To match both spatie-log sources, pass both keys: `->ofType(['activity_log', 'related_activity_log'])`. See the [type taxonomy](/concepts/how-it-works#type-taxonomy).
::

## Sorting
Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.essentials/6.configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Every knob the package exposes lives in `config/activity-log.php`. Publish it wi
| `pagination_buffer` | `int` | `2` | Per-source over-fetch multiplier: `cap = perPage × (page + buffer)`. See [/essentials/refining-the-timeline#pagination-buffer-mechanics](/essentials/refining-the-timeline#pagination-buffer-mechanics). |
| `deduplicate_by_default` | `bool` | `true` | Builder dedup default; overridable per-call via `->deduplicate(false)`. |
| `source_priorities.activity_log` | `int` | `10` | Priority for `ActivityLogSource`. |
| `source_priorities.related_activity_log` | `int` | `10` | Priority for `RelatedActivityLogSource`. **Note**: priority key only — entries from this source carry `type='activity_log'`, NOT `'related_activity_log'`. See [/concepts/how-it-works#type-taxonomy](/concepts/how-it-works#type-taxonomy). |
| `source_priorities.related_activity_log` | `int` | `10` | Priority for `RelatedActivityLogSource`. Entries from this source carry `type='related_activity_log'`. |
| `source_priorities.related_model` | `int` | `20` | Priority for `RelatedModelSource`. |
| `source_priorities.custom` | `int` | `30` | Priority for `CustomEventSource`. |
| `renderers` | `array` | `[]` | Event-or-type → renderer map. See [/essentials/customization#registration-channels](/essentials/customization#registration-channels). |
Expand Down
11 changes: 6 additions & 5 deletions docs/content/6.troubleshooting/1.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ Renderers resolve in this order: explicit `$entry->renderer` → `bindings[$entr

Dedup uses `dedupKey` + `sourcePriority`. If two sources emit the same logical event with different keys, they won't collapse. Either align `dedupKey` on both sources (use `->dedupKeyUsing()` on the builder) or raise the preferred source's priority so the loser is dropped. Mechanics at [/concepts/how-it-works#dedup-behavior](/concepts/how-it-works#dedup-behavior).

## Type filter doesn't match anything
## Cache invalidation flushed unrelated caches

::callout{icon="i-lucide-alert-triangle" color="warning"}
- **Symptom:** `$record->timeline()->fromActivityLogOf(['emails'])->ofType(['related_activity_log'])->get()` returns empty.
- **Cause:** `RelatedActivityLogSource` emits entries with `type='activity_log'` (NOT `'related_activity_log'`). The `related_activity_log` key only exists in `source_priorities` config — for priority configuration only.
- **Workaround:** filter with `->ofType(['activity_log'])` to include both own- and related-log entries. To distinguish them at the entry level, inspect `$entry->relatedModel` (`null` for `ActivityLogSource`, an Eloquent model for `RelatedActivityLogSource`).
- **Tracking:** [issue #11](https://github.com/relaticle/activity-log/issues/11).
- **Symptom:** after calling `$record->forgetTimelineCache()`, sessions / queue locks / application caches are gone too.
- **Cause:** `TimelineCache::forget()` calls `Cache::store(...)->getStore()->flush()` — flushes the entire cache store, not just this subject's keys.
- **Workaround:** configure `cache.store` to a dedicated Laravel cache store used only by the timeline. Or skip explicit invalidation and let TTL expire naturally (set a short `->cached($ttl)`).
- **Tracking:** [issue #12](https://github.com/relaticle/activity-log/issues/12).
- Full caveat at [/essentials/caching#invalidation--known-limitation](/essentials/caching#invalidation--known-limitation).
::

## `fromActivityLog()` throws on a fresh model
Expand Down
5 changes: 3 additions & 2 deletions src/ActivityLogServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public function packageBooted(): void
{
Livewire::component('activity-log', Filament\Livewire\ActivityLogLivewire::class);

$this->app->make(RendererRegistry::class)
->register('activity_log', Renderers\ActivityLogRenderer::class);
$registry = $this->app->make(RendererRegistry::class);
$registry->register('activity_log', Renderers\ActivityLogRenderer::class);
$registry->register('related_activity_log', Renderers\ActivityLogRenderer::class);
}
}
2 changes: 1 addition & 1 deletion src/Timeline/Sources/RelatedActivityLogSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private function makeEntry(Model $subject, ActivityModel $activity, Model $relat

return new TimelineEntry(
id: sprintf('related_activity_log:%s:%s', $activity->id, $event),
type: 'activity_log',
type: 'related_activity_log',
event: $event,
occurredAt: $occurredAt,
dedupKey: $this->dedupKeyFor($relatedModel::class, (string) $relatedModel->getKey(), $occurredAt),
Expand Down
2 changes: 1 addition & 1 deletion tests/Feature/BuilderDedupTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
->get();

expect($entries)->toHaveCount(1)
->and($entries->first()->type)->toBe('activity_log');
->and($entries->first()->type)->toBe('related_activity_log');
});

it('dedupKeyUsing() overrides the per-entry dedup key', function (): void {
Expand Down
Loading