Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e99fc6d70 | ||
|
|
12d6d30fb0 | ||
|
|
f9c14685b3 |
@@ -248,23 +248,30 @@ func (r *Runner) poll(ctx context.Context, scrapeSem, audioSem chan struct{}, wg
|
||||
}
|
||||
|
||||
// ── Audio tasks ───────────────────────────────────────────────────────
|
||||
// Only claim tasks when there is a free slot in the semaphore.
|
||||
// This avoids the old bug where we claimed (status→running) a task and
|
||||
// then couldn't dispatch it, leaving it orphaned until the reaper fired.
|
||||
audioLoop:
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
// Check capacity before claiming to avoid orphaning tasks.
|
||||
select {
|
||||
case audioSem <- struct{}{}:
|
||||
// Slot acquired — proceed to claim a task.
|
||||
default:
|
||||
// All slots busy; leave remaining pending tasks for next tick.
|
||||
break audioLoop
|
||||
}
|
||||
task, ok, err := r.deps.Consumer.ClaimNextAudioTask(ctx, r.cfg.WorkerID)
|
||||
if err != nil {
|
||||
<-audioSem // release the pre-acquired slot
|
||||
r.deps.Log.Error("runner: ClaimNextAudioTask failed", "err", err)
|
||||
break
|
||||
}
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
select {
|
||||
case audioSem <- struct{}{}:
|
||||
default:
|
||||
r.deps.Log.Warn("runner: audio semaphore full, will retry next tick",
|
||||
"task_id", task.ID)
|
||||
<-audioSem // release the pre-acquired slot; queue empty
|
||||
break
|
||||
}
|
||||
r.tasksRunning.Add(1)
|
||||
|
||||
@@ -247,8 +247,9 @@ func (c *pbClient) claimRecord(ctx context.Context, collection, workerID string,
|
||||
}
|
||||
|
||||
claim := map[string]any{
|
||||
"status": string(domain.TaskStatusRunning),
|
||||
"worker_id": workerID,
|
||||
"status": string(domain.TaskStatusRunning),
|
||||
"worker_id": workerID,
|
||||
"heartbeat_at": time.Now().UTC().Format(time.RFC3339),
|
||||
}
|
||||
for k, v := range extraClaim {
|
||||
claim[k] = v
|
||||
|
||||
@@ -4,7 +4,7 @@ import { getSettings } from '$lib/server/pocketbase';
|
||||
import { log } from '$lib/server/logger';
|
||||
|
||||
// Routes that are accessible without being logged in
|
||||
const PUBLIC_ROUTES = new Set(['/login']);
|
||||
const PUBLIC_ROUTES = new Set(['/login', '/disclaimer', '/privacy', '/dmca', '/terms']);
|
||||
|
||||
export const load: LayoutServerLoad = async ({ locals, url }) => {
|
||||
// Allow /auth/* (OAuth initiation + callbacks) without login
|
||||
|
||||
51
ui/src/routes/terms/+page.svelte
Normal file
51
ui/src/routes/terms/+page.svelte
Normal file
@@ -0,0 +1,51 @@
|
||||
<svelte:head>
|
||||
<title>Terms of Service — libnovel</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="max-w-2xl mx-auto py-10 px-4">
|
||||
<h1 class="text-2xl font-bold text-zinc-100 mb-6">Terms of Service</h1>
|
||||
|
||||
<div class="space-y-5 text-sm text-zinc-400 leading-relaxed">
|
||||
<p>
|
||||
By using libnovel you agree to these terms. If you do not agree, please do not use the service.
|
||||
</p>
|
||||
|
||||
<h2 class="text-base font-semibold text-zinc-200 mt-6">Use of the service</h2>
|
||||
<ul class="list-disc list-inside space-y-2 pl-1">
|
||||
<li>libnovel is provided for personal, non-commercial reading use only.</li>
|
||||
<li>You may not scrape, crawl, or systematically download content from the site.</li>
|
||||
<li>You may not use the service for any unlawful purpose.</li>
|
||||
<li>Accounts may be suspended or terminated for abuse.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="text-base font-semibold text-zinc-200 mt-6">Content</h2>
|
||||
<p>
|
||||
libnovel aggregates publicly available web novel content from third-party sources for
|
||||
personal reading convenience. We do not claim ownership of any novel content displayed on
|
||||
the site. If you are a rights holder and wish to have content removed, please see our
|
||||
<a href="/dmca" class="text-amber-400 hover:text-amber-300 transition-colors">DMCA policy</a>.
|
||||
</p>
|
||||
|
||||
<h2 class="text-base font-semibold text-zinc-200 mt-6">Accounts</h2>
|
||||
<p>
|
||||
You are responsible for maintaining the security of your account. libnovel is not liable
|
||||
for any loss or damage resulting from unauthorised access to your account.
|
||||
</p>
|
||||
|
||||
<h2 class="text-base font-semibold text-zinc-200 mt-6">Disclaimer of warranties</h2>
|
||||
<p>
|
||||
The service is provided "as is" without warranty of any kind. We do not guarantee
|
||||
availability, accuracy, or completeness of any content. See our full
|
||||
<a href="/disclaimer" class="text-amber-400 hover:text-amber-300 transition-colors">disclaimer</a>
|
||||
for details.
|
||||
</p>
|
||||
|
||||
<h2 class="text-base font-semibold text-zinc-200 mt-6">Changes to these terms</h2>
|
||||
<p>
|
||||
We may update these terms at any time. Continued use of the service after changes are
|
||||
posted constitutes acceptance of the revised terms.
|
||||
</p>
|
||||
|
||||
<p class="text-zinc-600 text-xs mt-8">Last updated: {new Date().getFullYear()}</p>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user