2.5 KiB
| name | description | version | category |
|---|---|---|---|
| standalone-sage-deployment | Sage-lib standalone deploy. DictObject/DBPools fixes. | 1.0.0 | devops |
Standalone Sage-Based App Deployment
When deploying standalone apps using Sage shared libs without the Sage framework.
Required Monkey-Patches
DictObject.getattr returns None not AttributeError
Blocks class-level method resolution. Must monkey-patch.
ServerEnv NOT a singleton
set_serverenv() needed for cross-instance values.
DBPools() defaults to empty
4 patches needed: sqlor.dbpools.get_sor_context, GlobalEnv cache, userperm, set_serverenv.
Ahserver dspy filename reservation
ANY dspy filename containing login, auth, signin, or identify returns 404 silently.
Use single dictionary words or random strings. Full list + debugging: see references/dspy-pitfalls.md.
dspy failure cache — PERMANENT
Once a dspy file fails, that filename is cached forever. Content change + restart does NOT clear it. Only fix: use a NEW filename. Copy from a working dspy first, then overwrite. See references/dspy-pitfalls.md.
aiohttp 3.10 route matching: prefix must be "" NOT "/"
ProcessorResource(prefix="/", dir="/d/xxx/wwwroot") — the "/" prefix causes
ProcessorResource._handle to NEVER be called; aiohttp falls through to SystemRoute._handle → 404.
Fix: use empty string prefix in config.json:
"paths": [["/d/pccs/wwwroot", ""]]
Single catch-all entry works — NO per-module paths needed. Empty prefix "" avoids aiohttp
3.10's StaticResource.resolve() bug with "/" prefix + session middleware interaction.
module_cache.rbac interaction
When enabled (default): share_cache calls Redis. Redis OFF → 500 for ALL requests.
Disable with "module_cache": {"rbac": false} in config.json if Redis not available.
Sage modules: setup.json not setup.py. Use symlinks for wwwroot.
Shared libs (ahserver, apppublic, sqlor, appbase, rbac) must be pip installed.
Sage modules (pcpool, pcc, etc.) have only setup.json — use ln -sfn for wwwroot symlinks.
DSPY login: must use password_encode() NOT SHA256
The Sage framework stores passwords via password_encode() which uses AES encryption.
In custom login dspy files, use the injected password_encode(password) function:
pw_encoded = password_encode(password)
# Compare with user.password from DB
if pw_encoded != (user.password or ''):
return {'status': 'error', 'message': '密码错误'}
SHA256 will never match the AES-encrypted stored value.