chore: drop verbose docblocks across PostHog and billing files

Class names and method signatures already explain what these classes
do. Project guideline (CLAUDE.md): comments only when the WHY is
non-obvious — implementation details belong in commits, not noise on
top of every class. Kept the one comment that earns it: the (int)
cast in HasUsage::cachedPostCount, which documents the load-bearing
workaround for Laravel's Redis cache numeric optimisation.
This commit is contained in:
Paulo Castellano 2026-05-07 16:03:12 -03:00
parent b682fd4359
commit ff23b5084b
6 changed files with 2 additions and 59 deletions

View file

@ -13,16 +13,6 @@
use Illuminate\Support\Facades\Log;
use PostHog\PostHog;
/**
* Low-level PostHog dispatch worker. Forwards a single API call (`capture`,
* `identify`, `groupIdentify`) to the PostHog SDK. Higher-level jobs in this
* namespace (`SyncUser`, `TrackBilling`) build the payloads and queue this
* job to do the network work.
*
* No-op when `POSTHOG_ENABLED` is false (or `POSTHOG_API_KEY` is unset),
* via `PostHogService::isEnabled()`, so self-hosted installs never reach
* the SDK.
*/
class SendEvent implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

View file

@ -12,22 +12,6 @@
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
/**
* Centralised PostHog sync for a single user. Dispatched from places the
* frontend can't observe (signup, Stripe webhooks) so the person profile
* and account/workspace groups carry up-to-date properties without blocking
* the calling request. Inertia navigations refresh group counts on the
* client (see `syncPostHogContext` in resources/js/posthog.ts), so this job
* is not needed on every domain trigger.
*
* Hierarchy mirrors the domain model:
* - person → User
* - group `account` → Account (billing/plan, parent of workspaces)
* - group `workspace` → Workspace (collaboration unit, child of account)
*
* No-op when PostHog is disabled (`POSTHOG_ENABLED=false` or no API key)
* via `PostHogService::isEnabled()`, so self-hosted installs are unaffected.
*/
class SyncUser implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

View file

@ -13,14 +13,6 @@
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
/**
* Captures a Stripe billing lifecycle event on the account owner profile
* with the `account` group attached, then re-queues `SyncUser` so the
* group properties (plan, has_active_subscription, is_on_trial) reflect
* the new Stripe state. Dispatched by `StripeEventListener`.
*
* No-op when PostHog is disabled (`POSTHOG_ENABLED=false` or no API key).
*/
class TrackBilling implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

View file

@ -32,13 +32,6 @@ class Account extends Model
'plan_id',
];
/**
* Drop the cached Pennant feature values for the plan-scoped limits so
* the next read resolves against the current plan. Call this right after
* any `plan_id` change. Centralised here (instead of as a model hook) so
* self-hosted installs — where Stripe webhooks never fire and the billing
* controllers redirect away — never trigger this path.
*/
public function forgetPlanFeatureCache(): void
{
Feature::for($this)->forget([

View file

@ -66,14 +66,8 @@ public function featureLimits(): array
}
/**
* The `(int)` cast on the cached value is load-bearing: Laravel's
* RedisStore skips serialize()/unserialize() for is_numeric values so
* they can be incremented atomically — the side effect is that an int
* stored via `Cache::put` comes back as a string on read. Without the
* cast, the strict `: int` return type throws a TypeError under the
* Redis cache driver (production). File/array/database drivers don't
* have this optimisation and preserve the type, which is why the bug
* never surfaced in tests or local dev.
* The `(int)` cast is load-bearing: Laravel's RedisStore stores numeric
* values raw (for atomic INCR) and returns them as strings on read.
*
* @param array<int, string> $workspaceIds
*/

View file

@ -10,12 +10,6 @@
class PostHogService
{
/**
* Whether PostHog tracking should run at all. Controlled by the explicit
* `POSTHOG_ENABLED` env var so self-hosted installs that inherited an
* example `POSTHOG_API_KEY` from a config snippet do not silently send
* events upstream. The SaaS deployment opts in via `POSTHOG_ENABLED=true`.
*/
public static function isEnabled(): bool
{
return (bool) config('services.posthog.enabled')
@ -23,10 +17,6 @@ public static function isEnabled(): bool
}
/**
* Capture an event for the given distinct id. When `$account` is supplied,
* the workspace/plan group is auto-attached so the event is filterable in
* PostHog by `$groups.account` and the `account_id` / `plan` properties.
*
* @param array<string, mixed> $properties
*/
public function capture(string $distinctId, string $event, array $properties = [], ?Account $account = null): void