Skip to content

Commit

Permalink
feat(env): select a valid DATABASE_URL when deployed on Railway.app
Browse files Browse the repository at this point in the history
Railway.app provides DATABASE_PRIVATE_URL, DATABASE_URL and/or
DATABASE_PUBLIC_URL. DATABASE_PRIVATE_URL is for private networking,
while DATABASE_PUBLIC_URL is for public networking. If private
networking is disabled, the former still exists but is invalid (i.e.,
missing host). If public networking is disabled, both host and port are
missing in the latter, resulting in an invalid URL too. A legacy
Postgres addon may provide only DATABASE_URL (for PUBLIC networking) and
DATABASE_PRIVATE_URL, while a modern one may provide only DATABASE_URL
(for PRIVATE networking) and DATABASE_PUBLIC_URL.

Thus, we need to select a valid one from them.

This should solve most database connection issues on Railway.app.

Signed-off-by: Rongrong <[email protected]>
  • Loading branch information
Rongronggg9 committed Aug 20, 2024
1 parent 354c6ea commit 6d6b44a
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Enhancements

- **Sanitize post title and author**: The title and author of a post (RSS item or Atom entry) are now sanitized to prevent unexpected formatting issues. In particular, unexpected whitespaces and linebreaks are removed, and any HTML elements are stripped. This helps display them correctly in Telegram messages as well as Telegraph posts.
- **Improve robustness on Railway.app**: Some Railway-specific environment variables are recognized to improve robustness on Railway.app. In particular, `DATABASE_PRIVATE_URL` and `DATABASE_PUBLIC_URL` will be used when `DATABASE_URL` is unavailable or invalid. This should solve most database connection issues on Railway.app.
- **Minor refactor**: Some internal functions have been refactored to improve readability and maintainability.

### Bug fixes
Expand Down
1 change: 1 addition & 0 deletions docs/CHANGELOG.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### 增强

- **净化文章标题和作者**: 文章 (RSS item 或 Atom entry) 的标题和作者现在被净化以防止意外的格式问题。特别是,预期外的空格和换行符被移除,任何 HTML 元素都被剥离。这有助于在 Telegram 消息以及 Telegraph 文章中正确显示它们。
- **改善在 Railway.app 上的稳健性**: 一些特定于 Railway 的环境变量被识别以提高在 Railway.app 上的稳健性。特别是,当 `DATABASE_URL` 不可用或无效时,将使用 `DATABASE_PRIVATE_URL``DATABASE_PUBLIC_URL`。这应该解决在 Railway.app 上的大多数数据库连接问题。
- **次要的重构**: 重构了一些内部函数以提高可读性和可维护性。

### Bug 修复
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ python-socks[asyncio]==2.5.0
dnspython[idna]==2.6.1

# utils
yarl==1.9.4
colorlog==6.8.2
APScheduler==3.10.4
python-dotenv==1.0.1
Expand Down
39 changes: 35 additions & 4 deletions src/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from typing_extensions import Final

import asyncio
import yarl
import os
import sys
import colorlog
Expand Down Expand Up @@ -316,11 +317,41 @@ def __get_version():
)
del _images_weserv_nl


# ----- db config -----
_database_url = os.environ.get('DATABASE_URL') or f'sqlite://{config_folder_path}/db.sqlite3'
DATABASE_URL: Final = (_database_url.replace('postgresql', 'postgres', 1) if _database_url.startswith('postgresql')
else _database_url)
del _database_url
def __get_database_url() -> str:
# Railway.app provides DATABASE_PRIVATE_URL, DATABASE_URL and/or DATABASE_PUBLIC_URL.
# DATABASE_PRIVATE_URL is for private networking, while DATABASE_PUBLIC_URL is for public networking.
# If private networking is disabled, the former still exists but is invalid (i.e., missing host).
# If public networking is disabled, both host and port are missing in the latter, resulting in an invalid URL too.
# A legacy Postgres addon may provide only DATABASE_URL (for PUBLIC networking) and DATABASE_PRIVATE_URL,
# while a modern one may provide only DATABASE_URL (for PRIVATE networking) and DATABASE_PUBLIC_URL.
# Thus, we need to select a valid one from them.
urls: tuple[str, ...] = tuple(filter(None, map(os.environ.get, (
'DATABASE_URL', # Generic, Railway.app compatible
'DATABASE_PRIVATE_URL', # Railway.app specific
'DATABASE_PUBLIC_URL', # Railway.app specific
))))
if not urls:
return f'sqlite://{config_folder_path}/db.sqlite3'
err: Optional[BaseException] = None
for url in urls:
try:
y_url = yarl.URL(url)
except ValueError as _err:
err = _err
else:
return str(
# Tortoise-ORM does not recognize 'postgresql' scheme
y_url.with_scheme('postgres')
if y_url.scheme == 'postgresql'
else y_url
)
else:
logger.critical('INVALID DATABASE URL!', exc_info=err)


DATABASE_URL: Final = __get_database_url()

# ----- misc config -----
TABLE_TO_IMAGE: Final = __bool_parser(os.environ.get('TABLE_TO_IMAGE'))
Expand Down

0 comments on commit 6d6b44a

Please sign in to comment.