Skip to content

feat: adjust default config for crawl and set concurrency to 5 - #50

Merged
4rokis merged 2 commits into
mainfrom
bugfix/bug-crawling-doesnt-get-all-the-pages
Jan 16, 2026
Merged

feat: adjust default config for crawl and set concurrency to 5#50
4rokis merged 2 commits into
mainfrom
bugfix/bug-crawling-doesnt-get-all-the-pages

Conversation

@Caknoooo

@Caknoooo Caknoooo commented Jan 6, 2026

Copy link
Copy Markdown
Collaborator

Bug Fix PR

Bug Summary

Linked #44

npm run cli -- crawl https://accesstime.co/en --skip-cache

> @accesstime/lenscore@0.2.0 cli
> tsx src/cli.ts crawl https://accesstime.co/en --skip-cache

⠋ Starting crawl...
🕷️ Crawling: https://accesstime.co/en

✔ LensCore is ready
✔ LensCore ready
✔ Crawl completed
✔ Crawl completed
{
  "pages": [
    {
      "url": "https://accesstime.co/en",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:06.976Z"
    },
    {
      "url": "https://accesstime.co/blog",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:08.510Z"
    },
    {
      "url": "https://accesstime.co/blog/accessibility-overlays-break-down",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:08.551Z"
    },
    {
      "url": "https://accesstime.co/blog/apple-accessibility-nutrition-labels",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:08.767Z"
    },
    {
      "url": "https://accesstime.co/api/rss",
      "title": "Untitled",
      "description": "",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:09.682Z"
    },
    {
      "url": "https://accesstime.co/blog/pour-principles",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:10.338Z"
    },
    {
      "url": "https://accesstime.co/blog/accessibility-in-gaming-industry",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:10.534Z"
    },
    {
      "url": "https://accesstime.co/blog/international-day-of-persons-with-disabilities-2025",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:12.037Z"
    },
    {
      "url": "https://accesstime.co/blog/ai-assisted-accessibility",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:12.584Z"
    }
  ],
  "totalPages": 9,
  "crawlTime": 8353,
  "metadata": {
    "crawledAt": "2026-01-06T11:48:13.351Z",
    "maxDepth": 2,
    "rules": {},
    "totalPages": 9,
    "crawlTime": 8353
  }
}
caknoo@Mac-Caknocomel-1141 LensCore % npm run cli -- crawl https://accesstime.co --skip-cache 

> @accesstime/lenscore@0.2.0 cli
> tsx src/cli.ts crawl https://accesstime.co --skip-cache

⠋ Starting crawl...
🕷️ Crawling: https://accesstime.co

✔ LensCore is ready
✔ LensCore ready
✔ Crawl completed
✔ Crawl completed
{
  "pages": [
    {
      "url": "https://accesstime.co",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:34.954Z"
    },
    {
      "url": "https://accesstime.co/blog/apple-accessibility-nutrition-labels",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:36.421Z"
    },
    {
      "url": "https://accesstime.co/blog",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:36.482Z"
    },
    {
      "url": "https://accesstime.co/en",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:36.536Z"
    },
    {
      "url": "https://accesstime.co/blog/accessibility-overlays-break-down",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:37.889Z"
    },
    {
      "url": "https://accesstime.co/blog/accessibility-in-gaming-industry",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:38.158Z"
    },
    {
      "url": "https://accesstime.co/blog/pour-principles",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:38.222Z"
    },
    {
      "url": "https://accesstime.co/api/rss",
      "title": "Untitled",
      "description": "",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:38.787Z"
    },
    {
      "url": "https://accesstime.co/blog/international-day-of-persons-with-disabilities-2025",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:39.928Z"
    },
    {
      "url": "https://accesstime.co/blog/ai-assisted-accessibility",
      "title": "AccessTime - Building a Web Without Barriers",
      "description": "Expert web accessibility consultation studio specializing in WCAG compliance audits, workshops, and training. We help businesses create inclusive digital experiences that work for everyone.",
      "statusCode": 200,
      "timestamp": "2026-01-06T11:48:40.363Z"
    }
  ],
  "totalPages": 10,
  "crawlTime": 6618,
  "metadata": {
    "crawledAt": "2026-01-06T11:48:40.380Z",
    "maxDepth": 2,
    "rules": {},
    "totalPages": 10,
    "crawlTime": 6618
  }
}

Root Cause

Summarize the underlying cause identified.

Fix

Describe the approach taken and alternatives considered.

Repro & Verification Steps

Steps to reproduce the bug and verify the fix.

Risk & Rollback Plan

Potential side effects and the rollback plan.

Checklist

  • Linked issue/bug report
  • Previously failing tests now pass / new tests added
  • Lint & build pass
  • No API changes without notes
  • Changelog updated if needed

@Caknoooo
Caknoooo requested a review from 4rokis January 6, 2026 11:52
@Caknoooo Caknoooo self-assigned this Jan 6, 2026
@Caknoooo Caknoooo linked an issue Jan 6, 2026 that may be closed by this pull request
3 tasks
@greptile-apps

greptile-apps Bot commented Jan 6, 2026

Copy link
Copy Markdown

Greptile Overview

Greptile Summary

This PR successfully fixes the critical bug in issue #44 where link discovery was incorrectly limited to the concurrency value (3-5 links per page), preventing complete site crawling. The key fix removes the nextItems.length < concurrency condition at line 214, allowing all discovered links to be queued for crawling.

What Changed:

  1. Bug Fix: Removed the artificial limit on link extraction that was preventing proper page discovery
  2. Cache Support: Added skipCache parameter to CrawlRequest interface and implemented cache bypass logic
  3. Type Safety: Updated TypeScript types to support the new skipCache option

Issues Found:

Critical:

  • Cache Inconsistency: When skipCache=true, the cache read is bypassed but results are still written to cache (lines 287-298), which may not be the intended behavior
  • Hardcoded Defaults: maxDepth defaults to 2 in two separate locations (lines 69, 129) instead of using a centralized configuration like other parameters (CRAWL_CONCURRENCY, CRAWL_MAX_URLS). This was mentioned in previous review threads but remains unresolved.

Minor:

  • Performance: Cache key generation (including MD5 hashing) runs even when skipCache=true
  • Memory Concern: Removing the link limit could allow thousands of links to be queued from a single page without bounds

Note: The PR title mentions "set concurrency to 5" and "adjust default config," but the code changes don't actually modify any default configuration values. The defaults remain in src/utils/env.ts (CRAWL_CONCURRENCY=5, CRAWL_MAX_URLS=25) and CLI (concurrency=3, maxUrls=10).

Confidence Score: 3/5

  • This PR fixes a critical bug but introduces a cache consistency issue that needs addressing before merge.
  • The core bug fix (removing the link limit) is correct and addresses the reported issue. However, the PR has a critical logic flaw where skipCache only prevents reading from cache but still writes to it, creating inconsistent behavior. Additionally, the hardcoded maxDepth defaults in multiple locations (previously flagged in review threads) remain unresolved, creating maintenance burden. The types file changes are clean. Score of 3 reflects: correct bug fix (+2), cache logic issue (-2), unresolved hardcoded defaults issue (-1), clean type changes (+1), minor performance concerns (-1), and misleading PR title (+0 as it's documentation only).
  • Pay close attention to src/services/crawling.ts - specifically the skipCache implementation at lines 93-110 and 287-298, and the hardcoded maxDepth defaults at lines 69 and 129.

Important Files Changed

File Analysis

Filename Score Overview
src/services/crawling.ts 3/5 Fixed critical link discovery bug but introduced cache inconsistency and has hardcoded defaults in multiple locations. The skipCache logic only prevents reading from cache but still writes to it, and maxDepth defaults are hardcoded in two places instead of using environment variables.
src/types/crawling.ts 5/5 Simple addition of skipCache optional boolean parameter to CrawlRequest interface. Clean, type-safe change with no issues.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI Command
    participant CS as CrawlingService
    participant Cache as CacheService
    participant Browser as Playwright Browser
    participant Queue as Crawl Queue
    
    CLI->>CS: crawlWebsite(request)
    
    alt skipCache is false
        CS->>Cache: get(cacheKey)
        alt cache hit
            Cache-->>CS: cached result
            CS-->>CLI: return cached result
        else cache miss
            Cache-->>CS: null
        end
    else skipCache is true
        Note over CS,Cache: Skip cache lookup
    end
    
    CS->>Browser: initialize()
    CS->>Queue: queue.push({url, depth: 0})
    
    loop while queue not empty AND results < maxUrls
        CS->>Queue: batch = queue.splice(0, concurrency)
        
        par Process batch concurrently
            CS->>Browser: crawlPage(item)
            Browser->>Browser: goto(url)
            Browser->>Browser: extract title, description
            CS->>CS: extractLinks($, url, baseUrl, rules)
            
            Note over CS: BUG FIX: Previously limited<br/>nextItems.length < concurrency<br/>Now: unlimited link discovery
            
            loop for each link found
                alt not visited
                    CS->>Queue: nextItems.push({url: link, depth+1})
                end
            end
            
            Browser-->>CS: return nextItems
        end
        
        CS->>Queue: queue.push(...nextItems)
    end
    
    alt skipCache implementation issue
        Note over CS,Cache: Currently always caches result<br/>even when skipCache=true
        CS->>Cache: set(cacheKey, result)
    end
    
    CS-->>CLI: return CrawlResponse
Loading

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (2)

  1. src/services/crawling.ts, line 69 (link)

    logic: Cache key generation still uses default maxDepth of 2, but new default is 3. This causes cache misses when default is used.

  2. src/services/crawling.ts, line 129 (link)

    logic: Default maxDepth still hardcoded to 2, inconsistent with new default of 3

4 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment thread src/cli/commands/crawl.ts Outdated
@Caknoooo Caknoooo changed the title feat: adjust default config for crawl and set concurrency to 3 feat: adjust default config for crawl and set concurrency to 5 Jan 6, 2026
@4rokis

4rokis commented Jan 6, 2026

Copy link
Copy Markdown
Collaborator

@Caknoooo Can you check the greptile comments?

@4rokis

4rokis commented Jan 12, 2026

Copy link
Copy Markdown
Collaborator

@Caknoooo So what was the problem, the maxUrl? WHy do we need to update the rest?

@Caknoooo

Caknoooo commented Jan 12, 2026

Copy link
Copy Markdown
Collaborator Author

@Caknoooo So what was the problem, the maxUrl? WHy do we need to update the rest?

After I try error, the problem was not maxUrl or the other default values.

The condition nextItems.length < concurrency was incorrectly limiting the number of links queued per page to only the concurrency value (3-5 links). This caused the crawler to skip most links on each page I think

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 files reviewed, 5 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps

greptile-apps Bot commented Jan 12, 2026

Copy link
Copy Markdown
Additional Comments (5)

src/services/crawling.ts
When skipCache is true, the cache retrieval is correctly skipped, but the results are still being cached at the end. This creates an inconsistency: if a user explicitly skips the cache, they likely don't want to write to it either. This could lead to unexpected behavior where a --skip-cache request still updates the cache, affecting subsequent cached requests.

Consider wrapping the cache write operation with the same skipCache check:

      if (!request.skipCache) {
        try {
          await this.cacheService.set(
            {
              ruleId: cacheKey,
              projectContext: {},
            },
            result
          );
          logger.info('Cached crawl result', { url: request.url });
        } catch (error) {
          logger.warn('Failed to cache crawl result', { error });
        }
      }

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/services/crawling.ts
Line: 287:298

Comment:
When `skipCache` is true, the cache retrieval is correctly skipped, but the results are still being cached at the end. This creates an inconsistency: if a user explicitly skips the cache, they likely don't want to write to it either. This could lead to unexpected behavior where a `--skip-cache` request still updates the cache, affecting subsequent cached requests.

Consider wrapping the cache write operation with the same `skipCache` check:

```suggestion
      if (!request.skipCache) {
        try {
          await this.cacheService.set(
            {
              ruleId: cacheKey,
              projectContext: {},
            },
            result
          );
          logger.info('Cached crawl result', { url: request.url });
        } catch (error) {
          logger.warn('Failed to cache crawl result', { error });
        }
      }
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

src/services/crawling.ts
The maxDepth is hardcoded to 2 when request.max_depth is not provided. This creates inconsistency across the codebase:

  1. This cache key generation uses hardcoded 2
  2. Line 129 also uses hardcoded 2
  3. The CLI defaults to 2 (src/cli.ts line 63, src/cli/commands/crawl.ts line 19)
  4. But the env configuration has CRAWL_CONCURRENCY and CRAWL_MAX_URLS defaults defined

There's no CRAWL_MAX_DEPTH environment variable defined in src/utils/env.ts, which means:

  • Users cannot configure the default maxDepth via environment variables
  • The cache key generation and actual crawling logic have the default hardcoded in two places, creating maintenance burden

This is a critical consistency issue mentioned in the previous review thread. Consider either:

  1. Adding CRAWL_MAX_DEPTH to env.ts with a default value and using env.CRAWL_MAX_DEPTH here, OR
  2. Extracting this default to a constant that's reused in both locations
      maxDepth: request.max_depth || parseInt(env.CRAWL_MAX_DEPTH || '2'),
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/services/crawling.ts
Line: 69:69

Comment:
The `maxDepth` is hardcoded to `2` when `request.max_depth` is not provided. This creates inconsistency across the codebase:

1. This cache key generation uses hardcoded `2`
2. Line 129 also uses hardcoded `2`
3. The CLI defaults to `2` (src/cli.ts line 63, src/cli/commands/crawl.ts line 19)
4. But the env configuration has `CRAWL_CONCURRENCY` and `CRAWL_MAX_URLS` defaults defined

There's no `CRAWL_MAX_DEPTH` environment variable defined in `src/utils/env.ts`, which means:
- Users cannot configure the default `maxDepth` via environment variables
- The cache key generation and actual crawling logic have the default hardcoded in two places, creating maintenance burden

This is a **critical consistency issue** mentioned in the previous review thread. Consider either:
1. Adding `CRAWL_MAX_DEPTH` to env.ts with a default value and using `env.CRAWL_MAX_DEPTH` here, OR
2. Extracting this default to a constant that's reused in both locations

```suggestion
      maxDepth: request.max_depth || parseInt(env.CRAWL_MAX_DEPTH || '2'),
```

How can I resolve this? If you propose a fix, please make it concise.

src/services/crawling.ts
Same hardcoded maxDepth default issue as line 69. This is the second location where maxDepth defaults to 2, creating a maintenance burden and inconsistency with how other configuration values are handled (which use env.CRAWL_* variables).

The proper fix requires adding CRAWL_MAX_DEPTH to src/utils/env.ts and using it here:

      const maxDepth = request.max_depth || parseInt(env.CRAWL_MAX_DEPTH || '2');
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/services/crawling.ts
Line: 129:129

Comment:
Same hardcoded `maxDepth` default issue as line 69. This is the second location where `maxDepth` defaults to `2`, creating a maintenance burden and inconsistency with how other configuration values are handled (which use `env.CRAWL_*` variables).

The proper fix requires adding `CRAWL_MAX_DEPTH` to `src/utils/env.ts` and using it here:

```suggestion
      const maxDepth = request.max_depth || parseInt(env.CRAWL_MAX_DEPTH || '2');
```

How can I resolve this? If you propose a fix, please make it concise.

src/services/crawling.ts
The generateCacheKey method is called unconditionally even when skipCache is true. While this doesn't cause errors, it's inefficient to generate a cache key (including MD5 hash computation) when it won't be used. Consider checking request.skipCache before calling this method, or passing skipCache as a parameter and returning early if it's true.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/services/crawling.ts
Line: 65:76

Comment:
The `generateCacheKey` method is called unconditionally even when `skipCache` is true. While this doesn't cause errors, it's inefficient to generate a cache key (including MD5 hash computation) when it won't be used. Consider checking `request.skipCache` before calling this method, or passing `skipCache` as a parameter and returning early if it's true.

How can I resolve this? If you propose a fix, please make it concise.

src/services/crawling.ts
The removal of nextItems.length < concurrency correctly fixes the bug where link discovery was artificially limited. However, this introduces a potential memory concern: if a page contains thousands of links, all of them will be added to nextItems and subsequently to the queue without any limit.

While the outer loop checks results.length < maxUrls (line 255), the queue itself can grow very large before those URLs are processed. Consider adding a safeguard to limit the total queue size or the number of links extracted per page. For example:

if (depth < maxDepth && results.length < maxUrls && queue.length + nextItems.length < maxUrls * 10) {
  const links = this.extractLinks($, url, baseUrl, rules);
  const remainingSlots = Math.max(0, (maxUrls * 10) - queue.length - nextItems.length);
  
  for (const link of links.slice(0, remainingSlots)) {
    if (!visited.has(link)) {
      nextItems.push({ url: link, depth: depth + 1 });
    }
  }
}

This isn't critical for typical websites, but could prevent issues with sites that have extensive link networks.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/services/crawling.ts
Line: 211:219

Comment:
The removal of `nextItems.length < concurrency` correctly fixes the bug where link discovery was artificially limited. However, this introduces a potential memory concern: if a page contains thousands of links, all of them will be added to `nextItems` and subsequently to the queue without any limit.

While the outer loop checks `results.length < maxUrls` (line 255), the queue itself can grow very large before those URLs are processed. Consider adding a safeguard to limit the total queue size or the number of links extracted per page. For example:

```typescript
if (depth < maxDepth && results.length < maxUrls && queue.length + nextItems.length < maxUrls * 10) {
  const links = this.extractLinks($, url, baseUrl, rules);
  const remainingSlots = Math.max(0, (maxUrls * 10) - queue.length - nextItems.length);
  
  for (const link of links.slice(0, remainingSlots)) {
    if (!visited.has(link)) {
      nextItems.push({ url: link, depth: depth + 1 });
    }
  }
}
```

This isn't critical for typical websites, but could prevent issues with sites that have extensive link networks.

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

@4rokis
4rokis merged commit 9145f7f into main Jan 16, 2026
3 of 4 checks passed
@4rokis
4rokis deleted the bugfix/bug-crawling-doesnt-get-all-the-pages branch January 16, 2026 01:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Crawling doesn't get all the pages

2 participants