Skip to content

fix(cron): make each job execution use an independent session#2474

Merged
yinwm merged 3 commits intosipeed:mainfrom
srcrs:fix-cron-independent-sessions
Apr 16, 2026
Merged

fix(cron): make each job execution use an independent session#2474
yinwm merged 3 commits intosipeed:mainfrom
srcrs:fix-cron-independent-sessions

Conversation

@srcrs
Copy link
Copy Markdown
Contributor

@srcrs srcrs commented Apr 10, 2026

📝 Description

Previously all executions of the same cron job reused the session key "cron-{jobID}", causing conversation history to accumulate across runs. Now each run gets a unique key "cron-{jobID}-{timestamp}", preventing cross-execution interference.

🗣️ Type of Change

  • [ x] 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • [x ] 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

📚 Technical Context (Skip for Docs)

  • Reference URL:
  • Reasoning: The cron job session key was previously "cron-{jobID}", causing each execution to accumulate in the same conversation history. Now it uses "cron-{jobID}-{timestamp}" to ensure each run gets an independent session.

☑️ Checklist

  • [x ] My code/docs follow the style of this project.
  • [x ] I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

Previously all executions of the same cron job reused the session key
"cron-{jobID}", causing conversation history to accumulate across runs.
Now each run gets a unique key "cron-{jobID}-{timestamp}", preventing
cross-execution interference.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 10, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown
Collaborator

@yinwm yinwm left a comment

Choose a reason for hiding this comment

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

Thanks for the fix! The core idea is correct — cron jobs should get independent sessions. However, there are two blocking issues:

1. Session key is silently ignored by resolveScopeKey

In pkg/agent/loop.go:1457-1462, resolveScopeKey only honors session keys prefixed with "agent:":

func resolveScopeKey(route routing.ResolvedRoute, msgSessionKey string) string {
    if msgSessionKey != "" && strings.HasPrefix(msgSessionKey, sessionKeyAgentPrefix) {
        return msgSessionKey
    }
    return route.SessionKey
}

The cron key "cron-{jobID}-{timestamp}" doesn't match this prefix, so it falls back to route.SessionKey (derived from channel/chatID). This means the fix may have no effect — multiple executions of the same cron job could still share a session.

Could you verify this by checking the actual scope_key in logs when a cron job fires? If confirmed, consider either:

  • Prefixing cron keys with "agent:" (e.g., "agent:cron-{jobID}-{timestamp}")
  • Or adding a special case in processMessage for cron-sourced messages

2. Test assertion is hardcoded to old format

pkg/tools/cron_test.go:274 still expects "cron-job-1" but the new format is "cron-job-1-{timestamp}". This will fail CI. Update to use a prefix match like strings.HasPrefix(executor.lastKey, "cron-job-1-").

Non-blocking suggestions:

  • Add a TTL/cleanup strategy for cron sessions to prevent unbounded disk and memory growth
  • Consider using UUID instead of time.Now().UnixMilli() to avoid collision in concurrent scenarios

…ves it

Cron session keys "agent:cron-{id}-{uuid}" were being silently ignored by
resolveScopeKey, which only recognizes keys prefixed with "agent:". This
caused multiple executions of the same job to share a session. Also
switch from timestamp to UUID to avoid collisions in concurrent scenarios.
@srcrs
Copy link
Copy Markdown
Contributor Author

srcrs commented Apr 11, 2026

Thanks for the fix! The core idea is correct — cron jobs should get independent sessions. However, there are two blocking issues:

1. Session key is silently ignored by resolveScopeKey

In pkg/agent/loop.go:1457-1462, resolveScopeKey only honors session keys prefixed with "agent:":

func resolveScopeKey(route routing.ResolvedRoute, msgSessionKey string) string {
    if msgSessionKey != "" && strings.HasPrefix(msgSessionKey, sessionKeyAgentPrefix) {
        return msgSessionKey
    }
    return route.SessionKey
}

The cron key "cron-{jobID}-{timestamp}" doesn't match this prefix, so it falls back to route.SessionKey (derived from channel/chatID). This means the fix may have no effect — multiple executions of the same cron job could still share a session.

Could you verify this by checking the actual scope_key in logs when a cron job fires? If confirmed, consider either:

  • Prefixing cron keys with "agent:" (e.g., "agent:cron-{jobID}-{timestamp}")
  • Or adding a special case in processMessage for cron-sourced messages

2. Test assertion is hardcoded to old format

pkg/tools/cron_test.go:274 still expects "cron-job-1" but the new format is "cron-job-1-{timestamp}". This will fail CI. Update to use a prefix match like strings.HasPrefix(executor.lastKey, "cron-job-1-").

Non-blocking suggestions:

  • Add a TTL/cleanup strategy for cron sessions to prevent unbounded disk and memory growth
  • Consider using UUID instead of time.Now().UnixMilli() to avoid collision in concurrent scenarios

fixed, testing is normal.

@afjcjsbx
Copy link
Copy Markdown
Collaborator

could you fix lint please? 🙏

… gci

gci linter requires a blank line separating import sections (default vs
localmodule). Missing separator caused CI failure.
@srcrs
Copy link
Copy Markdown
Contributor Author

srcrs commented Apr 14, 2026

could you fix lint please? 🙏

done

Copy link
Copy Markdown
Collaborator

@afjcjsbx afjcjsbx left a comment

Choose a reason for hiding this comment

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

LGTM

@afjcjsbx afjcjsbx requested a review from yinwm April 14, 2026 19:49
Copy link
Copy Markdown
Collaborator

@yinwm yinwm left a comment

Choose a reason for hiding this comment

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

LGTM. All blocking issues from the previous review have been addressed — the agent: prefix ensures resolveScopeKey honors the session key, UUID avoids collision, and tests are updated. Clean fix.

@yinwm yinwm merged commit ba08d52 into sipeed:main Apr 16, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: cron type: bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants