published() ->where('id', $id) ->first(); if (! $artwork) { return response()->json(['error' => 'Not found'], 404); } $sessionKey = 'art_viewed.' . $id; // Already counted this session — return early without touching the DB. if ($request->hasSession() && $request->session()->has($sessionKey)) { return response()->json(['ok' => true, 'counted' => false]); } // Write persistent event log (auth user_id or null for guests). $this->stats->logViewEvent((int) $artwork->id, $request->user()?->id); // Defer to Redis when available, fall back to direct DB increment. $this->stats->incrementViews((int) $artwork->id, 1, defer: true); $viewerId = $request->user()?->id; if ($artwork->user_id !== null && (int) $artwork->user_id !== (int) ($viewerId ?? 0)) { $this->xp->awardArtworkViewReceived( (int) $artwork->user_id, (int) $artwork->id, $viewerId, (string) $request->ip(), ); } // Mark this session so the artwork is not counted again. if ($request->hasSession()) { $request->session()->put($sessionKey, true); } return response()->json(['ok' => true, 'counted' => true]); } }