ä»ã¾ã§ããé£ã¹ããªã³ã´ã®å²åãã°ã©ãåããã¢ããªããGoogle Cloud Runã§åããã¦ãã¾ããã
Python + Django + Highcharts + Coogle Cloud Cloud Run + Cloud Storage + Litestream ã§é£ã¹ããªã³ã´ã®å²åãã°ã©ãåãã¦ã¿ã - ã¡ã¢çãªæèçãª
ã
éç¨ããä¸ã§ã
- ã³ã¼ã«ãã¹ã¿ã¼ããããæ°ã«ãªã
- ãã£ãã«ä½¿ããªãã¢ããªã¨ã¯ããã使ãã¨ãã«ã¯ãã£ã¨èµ·åããã¨å¬ãã
- DB(Litestream + SQLite)ãCloud Storageã«ç½®ãã¦ããã®ã§ããã¼ãã«ã®ä¸èº«ã確èªãã¥ãã
- Cloud Runã¯ã»ã¨ãã©è²»ç¨è² æ
ãçºçãã¦ããªãä¸æ¹ã§ãCloud Storageã§è²»ç¨ããããã§ãã
ãªã©ãæãããã¨ãããã¾ããã
ã
ãããªä¸ãCloudflareããã¼ã¿ãã¼ã¹æ©è½ã®D1ãæ£å¼ãªãªã¼ã¹ãã¾ããã
ãã¼ã¿ãã¼ã¹ããããªãã°ç§»è¡å
ã¨ãã¦ä½¿ãããããããªãã¨èããå¿
è¦ãããªæ©è½ãæ¤è¨¼ãã¦ãã¾ããã
ã
ã¾ãã d1-jdbc-driver
ã使ããã¨ã§ãD1ã«ãããã¼ãã«ãJetBrains DataGripãã確èªãããã¨ãã§ãã¾ããã
JetBrains IDEã§å¤é¨ãã¼ã表示ã§ãããããCloudflare D1åãJDBC driverãd1-jdbc-driverããä¿®æ£ãããã«ãªã¯ãä½ã£ã - ã¡ã¢çãªæèçãª
ã
以ä¸ããã移è¡ãã¦ãåé¡ãªãããã¨å¤æãã¾ããã
ããã§ãä»ã¾ã§ã®æ¤è¨¼ã«å ãã¦ç§»è¡ä½æ¥ãè¡ã£ããããå
容ãã¡ã¢ãã¦ããã¾ãã
ãªãã移è¡å¾ã®Webã¢ããªã®URLã¯ä»¥ä¸ã§ãã
https://ringosky.thinkami.dev/
ã
ç®æ¬¡
ã
ç°å¢
- Windows 11 WSL2
- Wrangler 3.60.3
- Bun 1.1.13
- Bunã®workspaceã使ã£ã¦ã¢ãã¬ãã§ç®¡ç
- ããã³ãã¨ã³ã
- React 18.3.1
- Chart.js 4.4.2
- react-chartjs-2 5.2.0
- TanStack Router 1.38.1
- TanStack Query 5.45.1
- ããã¯ã¨ã³ã
- Hono 4.4.12
- Drizzle ORM 0.31.2
- Drizzle Kit 0.22.7
- @atproto/api 0.12.23
- Bluesky APIç¨ã©ã¤ãã©ãª
- éçºåããã¼ã«
ã
ã¡ãªã¿ã«ããããã®ã½ã¼ã¹ã³ã¼ãã¯ãBunã®workspaceã使ã£ã¦ã¢ãã¬ãã§ç®¡çãã¦ãã¾ãã
ã
ã¾ãã移è¡åå¾ã§ä½¿ã£ã¦ããæ©è½ã¯ä»¥ä¸ã®éãã§ãã
Google Cloudã 㨠|
å½¹å² |
Cloudflareã§ã¯ |
Cloud Run |
ã¢ããªããã¹ã |
Pages + Workers + Service Binding(RPC) |
SQLite + Litestream + Cloud Storage |
ã¢ããªã®ãã¼ã¿ãã¼ã¹ |
D1 |
Cloud Scheduler |
SNSã¸ã®æ稿ãå®æçã«åé |
Workersã®Cron Trigger + KV |
ã
ã¾ãããããªæã㧠Cloudflare ã使ã£ã¦ãã¾ãã Pages 㨠Workers 㯠Service Binding (RPC) ã§é£æºãã¦ãã¾ãã
ãªããä¸å³ã®å種ã¢ã¤ã³ã³ã¯ä»¥ä¸ã®ãã¼ã¸ãããåããã¦ãã¾ãã
Brand Icons - Cloudflare Datamining
ã
以éã§ã¯ãã©ããªæãã§ã¢ããªãä½æã»ç§»è¡ããã®ããã¡ã¢ãã¦ããã¾ãã
ãªããè¨äºä¸ã§ã¯ã½ã¼ã¹ã³ã¼ããå¿
è¦ãªé¨åã ãæ示ãã¦ãã¾ãã
ã½ã¼ã¹ã³ã¼ãå
¨ä½ã¯ä»¥ä¸ã®ãªãã¸ããªã§å
¬éãã¦ãããããå¿
è¦ã«å¿ãã¦ãã¡ãã確èªãã¦ãã ããã
https://github.com/thinkAmi/cf_ringo_sky
ã
ã«ã¼ããã£ã¬ã¯ããªã§ã®ã»ããã¢ãã
ã¢ãã¬ãå
ã®PagesãWorkersãå
±éã§ä½¿ããã®ãã»ããã¢ãããã¾ãã
ã
ã©ã¤ãã©ãªã®ã¤ã³ã¹ãã¼ã«ã¨è¨å®ãã¡ã¤ã«ã®ç¨æ
wranglerã¨concurrentlyãã¤ã³ã¹ãã¼ã«ãã¾ãã
$ bun add -d wrangler concurrently
ã
Linter & Formatterã¨ã㦠Biome ãã¤ã³ã¹ãã¼ã«ãã¾ãã
$ bun add --dev --exact @biomejs/biome
ã
Biomeã®è¨å®ãã¡ã¤ã«ã¸ã³ã¡ã³ããæ¸ãããã biome.jsonc
ã¨ãã¦ç¨æãã¾ãã
https://github.com/thinkAmi/cf_ringo_sky/blob/main/biome.jsonc
ã
Bun workspace ã使ãããã« package.jsonãç·¨é
ä»åã®ã¢ããªãã¢ãã¬ãã§éçºã§ãããããBunã®workspaceæ©è½ã使ãã¾ãã
Workspaces â Package manager | Bun Docs
ã¾ãã concurrently
ã使ã£ã¦PagesãWorkersãä¸æ¬èµ·åã§ããããã« script
ãè¨å®ãã¾ãã
{
"private": true,
"scripts": {
"dev": "concurrently \"bun run --filter=\"ringo-db\" dev:db\" \"bun run --filter=\"ringo-web\" dev:web\""
},
"workspaces": ["packages/*"],
// ...
}
ã
ringo-db Workersã®ä½æ
åè¿°ã®éããService Binding RPCã使ã£ã¦Pagesã¨Workersãé£æºãã¾ãã
ããã§ãã¾ãã¯
- D1ã¨æ¥ç¶ããSQLãçºè¡ãã
- Service Binding RPCåãã«ãã¡ã½ãããå
¬éãã
ãæ
å½ãã ringo-db
Workersãä½æãã¾ãã
ã
ã©ã¤ãã©ãªã®ã¤ã³ã¹ãã¼ã«
Workersã®éå½¢ãä½ãã«ã¯ãCloudflare C3ã§ä½æããã®ã便å©ã§ãããã ãä»åã®Workersåãã«ã¯ä¸è¦ãªãã®ãã§ãã¦ãã¾ãã¾ãã
ããã§ãä»å㯠bun init
ã«ããæå°éã®ãã®ã ãçæãã¾ããã
bun init â Templating | Bun Docs
# packages ãã£ã¬ã¯ããªã®ä¸ã§ä½æ¥
$ mkdir ringo-db
$ cd ringo-db
# ringo-db ã¢ããªãçæ
$ bun init
...
package name (ringo-db):
entry point (index.ts): ./src/index.ts
Done! A package.json file was saved in the current directory.
+ ./src/index.ts
+ .gitignore
+ tsconfig.json (for editor auto-complete)
+ README.md
...
ã
ç¶ãã¦ãD1æ¥ç¶ã«å¿
è¦ãª Drizzle ORM ã¾ãããã¤ã³ã¹ãã¼ã«ãã¾ãã
$ bun add drizzle-orm
...
installed [email protected]
åããã¦ãéçºåãã« Drizzle Kit ãã¤ã³ã¹ãã¼ã«ãã¾ãã
$ bun add -D drizzle-kit
...
installed [email protected] with binaries:
- drizzle-kit
ã
Cloudflare D1ãä½æ
次ã«ãCloudflare D1ã wrangler ã§ä½æãã¾ããdatabase leaderã¯æ示çã« apac
ãæå®ãã¦ããã¾ãã
create | D1 | Commands - Wrangler · Cloudflare Workers docs
$ wrangler d1 create ringodb --location apac
...
â
Successfully created DB 'ringodb' in region APAC
Created your new D1 database.
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "ringodb"
database_id = "01febb3d-148f-4f3c-8fea-e32445da1ae1"
ã
D1ã®æ
å ±ã®ã»ãã compatibility_date
ã port
ãªã©ãæå®ãã¦ããã¾ãã
Configuration - Wrangler · Cloudflare Workers docs
name = "ringo-db"
main = "./src/index.ts"
compatibility_date = "2024-06-18"
compatibility_flags = [ "nodejs_compat" ]
[dev]
port = 8788
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "ringodb"
database_id = "01febb3d-148f-4f3c-8fea-e32445da1ae1"
ã
drizzle.config.ts ã®ä½æ
Drizzle ORMã®è¨å®ãã¡ã¤ã«ãä½æãã¾ãã
ãªããä»åã®ãã¤ã°ã¬ã¼ã·ã§ã³é©ç¨ã¯ãDrizzle Kit ã§ã¯ãªã Cloudflare D1 ã® Migrationã使ãã¾ãã
Migrations · Cloudflare D1 docs
ãã®ãããCloudflare D1ã®Migrationã®ä»æ§ã«åããã¦ã out
㯠migrations
ã«ãã¦ããã¾ãã
import type {Config} from "drizzle-kit"
export default {
dialect: "sqlite",
schema: "./db/schema/*",
out: "./migrations",
} satisfies Config
ã
ãã¼ã¿ãã¼ã¹ã®ã¹ãã¼ããä½æ
Blueskyã®æ稿ãä¿åããããã®ãã¼ãã« feeds
åãã®ã¹ãã¼ãã¨ãã¦ãringo-db/db/schema/feeds.ts
ãä½æãã¾ãã
import { sql } from 'drizzle-orm'
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
export const feeds = sqliteTable('feeds', {
id: integer('id', { mode: 'number' }).primaryKey({ autoIncrement: true }),
name: text('name'),
content: text('content'),
createdAt: text('created_at').default(sql`(CURRENT_TIMESTAMP)`),
snsId: text('sns_id'),
})
ã
ãã¤ã°ã¬ã¼ã·ã§ã³ãã¡ã¤ã«ã drizzle-kit
ã使ã£ã¦çæãã¾ãã
Generate migrations | Drizzle ORM - List of commands
$ bun drizzle-kit generate
drizzle-kit: v0.22.7
drizzle-orm: v0.31.2
No config path provided, using default 'drizzle.config.ts'
Reading config file 'path/to/ringo_sky/packages/ringo-db/drizzle.config.ts'
1 tables
feeds 5 columns 0 indexes 0 fks
[â] Your SQL migration file â migrations/0000_wild_pride.sql ð
ã
ãã¼ã«ã«ã®Cloudflare D1対ãã¦ãã¤ã°ã¬ã¼ã·ã§ã³ãé©ç¨ããå ´åãdrizzle-kit ã®æ©è½ã¯ä½¿ãã¾ããã
ããã§ãä»å㯠wrangler
ã使ã£ã¦ãã¤ã°ã¬ã¼ã·ã§ã³ãé©ç¨ãã¾ãã
ã¡ãªã¿ã«ããã¼ã«ã«ã«é©ç¨ãã --local
ãªãã·ã§ã³ãæ示çã«ä»ãã¦ããã¾ãã
https://developers.cloudflare.com/workers/wrangler/commands/#migrations-apply
$ wrangler d1 migrations apply ringodb --local
...
Migrations to be applied:
âââââââââââââââââââââââ
â name â
âââââââââââââââââââââââ¤
â 0000_wild_pride.sql â
âââââââââââââââââââââââ
â About to apply 1 migration(s)
Your database may not be available to serve requests during the migration, continue? ⦠yes
ð Executing on local database ringodb (01febb3d-148f-4f3c-8fea-e32445da1ae1) from .wrangler/state/v3/d1:
ð To execute on your remote database, add a --remote flag to your wrangler command.
âââââââââââââââââââââââ¬âââââââââ
â name â status â
âââââââââââââââââââââââ¼âââââââââ¤
â 0000_wild_pride.sql â â
â
âââââââââââââââââââââââ´âââââââââ
ã
ç¶ãã¦ãæ¬çªç°å¢ã§ãã Cloudflare D1 ã«ãã¤ã°ã¬ã¼ã·ã§ã³ãé©ç¨ãã¾ãã
$ wrangler d1 migrations apply ringodb --remote
...
Migrations to be applied:
âââââââââââââââââââââââ
â name â
âââââââââââââââââââââââ¤
â 0000_wild_pride.sql â
âââââââââââââââââââââââ
â About to apply 1 migration(s)
Your database may not be available to serve requests during the migration, continue? ⦠yes
ð Executing on remote database ringodb (01febb3d-148f-4f3c-8fea-e32445da1ae1):
ð To execute on your local development database, remove the --remote flag from your wrangler command.
ð£ Executed 2 commands in 0.4022ms
âââââââââââââââââââââââ¬âââââââââ
â name â status â
âââââââââââââââââââââââ¼âââââââââ¤
â 0000_wild_pride.sql â â
â
âââââââââââââââââââââââ´âââââââââ
ã
å®è£
ã«é¢ããã¡ã¢
ãã¨ã¯ã src/index.ts
ãªã©ã«å¿
è¦ãªæ©è½ãå®è£
ãã¾ãã
https://github.com/thinkAmi/cf_ringo_sky/blob/main/packages/ringo-db/src/index.ts
å®è£
ã§è¿·ã£ããã¨ã¯ä»¥ä¸ã§ãã
ã
以ä¸ã®è¨äºã«ããéããCloudflare D1ã«ã¯SQLã®ãã©ã³ã¶ã¯ã·ã§ã³ãå®è£
ããã¦ããªãããã§ãã
ã
ããã§ãSQLã®ãã©ã³ã¶ã¯ã·ã§ã³ãå¿
è¦ã«ãªã£ãã¨ã㯠batch APIã使ã£ã¦å®è£
ãã¾ããã
ã
Drizzle ORMã§Group By ã Count ãã
Drizzle ORMã®ããã¥ã¡ã³ãã«å¾ãå®è£
ãã¾ããã
ãªã ringo-db
Workers 㯠Service Binding RPC ã§å©ç¨ãããã¨ãåæã«ãã¦ãããã
WorkerEntrypoint
ãç¶æ¿ããã¯ã©ã¹ã«ãå
¬éããã¡ã½ãããå®ç¾©
- ã¨ã©ã¼ã«ãªãã®ãé²ããããdefault export ãããªãã¸ã§ã¯ãã«ã¯ããã¼ã®
fetch
ãå®ç¾©
ã¨ãã¦ãã¾ãã
ã
ã
ringo-web Pagesã®ä½æ
次ã«ãPages ã§ãã ringo-web
ãä½æãã¾ãã
ãã®Pagesã§ã¯
- ringo-db Workers 㨠Service Binding RPC ãã¦ãD1ã®ãã¼ã¿ãåãåã
- D1ã®ãã¼ã¿ãå
ã«ããã©ã¦ã¶ã§æç»ãã
ãæ
å½ãã¾ãã
ã
ã©ã¤ãã©ãªã®ã¤ã³ã¹ãã¼ã«
packages
ãã£ã¬ã¯ããªã®ä¸ã§ã create hono
ã«ããHonoã¢ããªã®éå½¢ãä½æãã¾ãã
# ã¤ã³ã¹ãã¼ã«
$ bun create hono ringo-web
create-hono version 0.7.1
â Using target directory ⦠ringo-web
? Which template do you want to use? cloudflare-pages
â Cloning the template
? Do you want to install project dependencies? yes
? Which package manager do you want to use? bun
â Installing project dependencies
ð Copied project files
Get started with: cd ringo-web
# ringo-webãã£ã¬ã¯ããªã¸ç§»å
$ cd ringo-web
ã
次ã«å¿
è¦ãªã©ã¤ãã©ãªãã¤ã³ã¹ãã¼ã«ãã¾ãã
Reactã¾ããã§ãã
$ bun add react react-dom
...
installed [email protected]
installed [email protected]
$ bun add -d @types/react @types/react-dom
...
installed @types/[email protected]
installed @types/[email protected]
ã
Chart.js ã¾ããã§ãã
$ bun add chart.js react-chartjs-2
...
installed [email protected]
installed [email protected]
ã
TanStack Routerã¾ããã§ãã
$ bun add @tanstack/react-router
...
installed @tanstack/[email protected]
$ bun add -D @tanstack/router-vite-plugin @tanstack/router-devtools @tanstack/router-cli
...
installed @tanstack/[email protected]
installed @tanstack/[email protected]
installed @tanstack/[email protected] with binaries:
- tsr
ã
TanStack Queryã¾ããã§ãã
$ bun add @tanstack/react-query
...
installed @tanstack/[email protected]
ã
compatibility_date
ãªã©ãè¨å®ãã¦ããã¾ãã
ãªããä»åã® compatibility_date
ã«ã¯ãéçºãå§ããé ã®æ¥ä» 2024-06-18
ãè¨å®ãã¦ããã¾ãã
name = "ringo-web"
pages_build_output_dir = "./dist"
compatibility_date = "2024-06-18"
ã
å®è£
ã«é¢ããã¡ã¢
YAMLãJSONã¸å¤æããã®ã« yq ã使ã£ã
ä»ã¾ã§ãããã«é¢ããæ
å ±ã¯ apples.yaml
ã¨ãããã¡ã¤ã«ã§ç®¡çãã¦ãã¾ããã
https://github.com/thinkAmi/dj_ringo_tabetter/blob/development/apples.yaml
ä»åãCloudflareã¸ç§»è¡ããã«ããããã½ã¼ã¹ã³ã¼ãã¯ãã¹ã¦TypeScriptã«ãªãã¾ãããããã§ãYAMLã§ã®ç®¡çããããTypeScriptã§ç®¡çãããã¨ãèãã¾ããã
ã
YAMLãJSONã¸å¤æãããã¼ã«ãæ¢ããã¨ããã yq
ããã£ãããã使ã£ã¦ã¿ããã¨ã«ãã¾ããã
https://github.com/mikefarah/yq
ã¾ãã¯ã¤ã³ã¹ãã¼ã«ãã¾ãã
$ sudo snap install yq
yq v4.40.5 from Mike Farah (mikefarah) installed
ã
ç¶ãã¦ãJSONãã¡ã¤ã«ã¸ã¨å¤æãã¾ãã
$ yq -o json ./old_data/apples.yml > ./src/apples.json
ã
ãã¨ã¯ãã¡ã¤ã«ã«ä¿åãããJSONãTypeScriptãã¡ã¤ã«ã¸ã¨ç§»æ¤ã»ä¿®æ£ãã¦ä½¿ãã¾ãã
ã
ãããã¤ãããã¨ããã¨viteãéä¸ã§ãã³ã°ããã®ã§ãããããåãã
éå»è¨äºã§ãæ¸ãã¾ããããPagesããããã¤ãããã¨ããã¨ãã³ã°ãã¦ãã¾ãã¾ãã
ããã§ãããã³ãã¨ã³ãã»ããã¯ã¨ã³ãã»ãããã¤ã®3段éã«åãã¦ãã«ãã»ãããã¤ãã¾ãã
ãã ãåãã«ãã§ã¯éä¸ã§ãã³ã°ããã®ã§ãéä¸ã§ãã£ã³ã»ã«ãã¦ãã¾ãã
ã¾ãã¯ããã³ãã¨ã³ãã®ãã«ã
$ bun run build:fe
...
dist/static/index.lazy-B-SIKAr-.js 1.01 kB â gzip: 0.60 kB
dist/static/month.lazy-mKjT0B0Q.js 1.06 kB â gzip: 0.64 kB
dist/static/appleLegendPlugin-C9-uDFHk.js 201.77 kB â gzip: 70.46 kB
dist/static/client.js 213.00 kB â gzip: 68.13 kB
â built in 1.33s
^C # ãã³ã°ããã®ã§ãã£ã³ã»ã«
ã
ç¶ãã¦ããã¯ã¨ã³ãã§ãã
$ bun run build:be
$ vite build
vite v5.3.1 building SSR bundle for production...
â 21 modules transformed.
dist/_worker.js 22.64 kB
â built in 196ms
^C # ãã³ã°ããã®ã§ãã£ã³ã»ã«
ã
æå¾ã«ãããã¤ãã¾ãã
$ bun run deploy
$ wrangler pages deploy dist
The project you specified does not exist: "ringo-web". Would you like to create it?"
⯠Create a new project
â Enter the production branch name: ⦠main
⨠Successfully created the 'ringo-web' project.
ð Uploading... (5/5)
⨠Success! Uploaded 5 files (2.38 sec)
⨠Compiled Worker successfully
⨠Uploading Worker bundle
⨠Uploading _routes.json
ð Deploying...
⨠Deployment complete! Take a peek over at https://578e4ac8.ringo-web.pages.dev
ã
ringo-bsky Workersã®ä½æ
æå¾ã«ã Blueskyãããªã³ã´ã®æ稿ãå®æçã«åå¾ãã ringo-sky
Workersãä½æãã¾ãã
ã
ã©ã¤ãã©ãªã®ã¤ã³ã¹ãã¼ã«
packages
ãã£ã¬ã¯ããªã®ä¸ã« ringo-bsky
ãä½æãããã®ä¸ã§ bun init
ãã¾ãã
$ bun init
bun init helps you get started with a minimal project and tries to guess sensible defaults. Press ^C anytime to quit
package name (ringo-bsky):
entry point (index.ts):
Done! A package.json file was saved in the current directory.
+ index.ts
+ .gitignore
+ tsconfig.json (for editor auto-complete)
+ README.md
To get started, run:
bun run index.ts
ã
ç¶ãã¦ãBlueskyã«ã¢ã¯ã»ã¹ããããã®ã©ã¤ãã©ãª @atproto/api
ãã¤ã³ã¹ãã¼ã«ãã¾ãã
https://www.npmjs.com/package/@atproto/api
$ bun add @atproto/api
bun add v1.1.13 (bd6a6051)
installed @atproto/[email protected]
11 packages installed [3.82s]
ã
Blueskyã®ã¯ã¬ãã³ã·ã£ã«ããã¼ã«ã«ã»æ¬çªç°å¢ã¸è¨å®
Blueskyã®æ稿ãåå¾ããããã«ãã¯ã¬ãã³ã·ã£ã«ãè¨å®ãã¾ãã
Workersã§ã¯ã¯ã¬ãã³ã·ã£ã«ã¯
- ãã¼ã«ã«ç°å¢ã¯
.dev.env
ãã¡ã¤ã«
- æ¬çªç°å¢ã¯ wrangler ã®ã³ãã³ã
ã使ãã¾ãã
Secrets · Cloudflare Workers docs
ã
ã¾ãããã¼ã«ã«ç°å¢åãã«ã¯ ringo-bsky
ãã£ã¬ã¯ããªã®ç´ä¸ã« .dev.env
ãã¡ã¤ã«ãçæãã¾ããä¸èº«ã«ã¯ä»¥ä¸ã®ã¯ã¬ãã³ã·ã£ã«æ
å ±ãè¨å®ãã¦ããã¾ãã
IDENTIFIER=èªåã®DID
APP_PASSWORD=ã¢ããªãã¹ã¯ã¼ãã®å¤
ã
次ã«ãwranglerã使ã£ã¦æ¬çªç°å¢ç¨ã®ã¯ã¬ãã³ã·ã£ã«ãè¨å®ãã¾ãã
ã¾ã㯠IDENTIFIER
ãè¨å®ãã¾ãã
$ wrangler secret put IDENTIFIER
...
â Enter a secret value: ⦠********************
ð Creating the secret for the Worker "ringo-bsky"
⨠Success! Uploaded secret IDENTIFIER
ã
次㫠APP_PASSWORD
ãè¨å®ãã¾ãã
$ wrangler secret put APP_PASSWORD
...
â Enter a secret value: ⦠*******************
ð Creating the secret for the Worker "ringo-bsky"
⨠Success! Uploaded secret APP_PASSWORD
ã
ãªãã wrangler secret put
ããã¨ãwrangler.toml ã®æ
å ±ããã¨ã« Cloudflare Workersãèªåã§ä½æããã¾ãã
ãã®ã¨ãã«ä½æããã Workers ã確èªããã¨ãã
- åå㯠wrangler.tomlã§æå®ãã
name
- Environment ã«ã·ã¼ã¯ã¬ãããè¨å®æ¸
- ã½ã¼ã¹ã³ã¼ãã¯
export default { fetch() {} }
ã®ã¿
ã¨ããç¶æ
ã§ããã
ã
KV ã¸å¦çæ¸ã®æ稿ã«é¢ããæ
å ±ãè¨é²
Blueskyããæ稿ãåå¾ã»ä¿åããéãéè¤ãã¦ãã¼ã¿ãä¿åããªããããååã©ãã¾ã§ä¿åãããããè¨é²ãã¦ããå¿
è¦ãããã¾ãã
ä»ã¾ã§ã¯DBã¸ä¿åãã¦ãã¾ããããã ãCloudflareã«ã¯ KV
ã¨ãããã¼ããªã¥ã¼ã¹ãã¢ãããã¾ãã
Cloudflare Workers KV · Cloudflare Workers KV
ãååã©ãã¾ã§ä¿åããããã¨ããæ
å ±ã¯1åã ãåå¨ãã¦ããã°ããã®ã§ãä»å㯠KV ã使ã£ã¦ä¿åãããã¨ã«ãã¾ãã
ã
ã¾ã㯠wrangler ã§ã°ãã¼ãã«ãªKVãä½æãã¾ãã
ãªããwrangler kv:namespace
ã³ãã³ãã®warningãåºã¦ãã¾ãããã¾ã ããã¥ã¡ã³ãã«ã¯åæ ããã¦ããªãããã§ããã¾ããwarningãªã®ã§ãKVã¯ã§ãã¦ããããã§ãã
https://developers.cloudflare.com/workers/wrangler/commands/#create-3
$ wrangler kv:namespace create LAST_CURSOR_KV
â² [WARNING] The `wrangler kv:namespace` command is deprecated and will be removed in a future major version. Please use `wrangler kv namespace` instead which behaves the same.
...
ð Creating namespace with title "ringo-bsky-LAST_CURSOR_KV"
⨠Success!
Add the following to your configuration file in your kv_namespaces array:
[[kv_namespaces]]
binding = "LAST_CURSOR_KV"
id = "f6f608a043
ã
ç¶ãã¦ãåãã³ãã³ãã« --preview
ãªãã·ã§ã³ãä»ãã¦ããã¼ã«ã«ã®KVãä½æãã¾ãã
ãªããwarningã§æ示ãããã³ãã³ã wrangler kv namespace
ã使ã£ãã¨ãããwarningãæ¶ãã¾ããã
$ wrangler kv namespace create LAST_CURSOR_KV --preview
...
ð Creating namespace with title "ringo-bsky-LAST_CURSOR_KV_preview"
⨠Success!
Add the following to your configuration file in your kv_namespaces array:
[[kv_namespaces]]
binding = "LAST_CURSOR_KV"
preview_id = "54ad69fc39bc429597e55ed0fe7acdd9"
ã
æå¾ã«ãwrangler.toml ã« KV ã®è¨å®ã追å ãã¾ãã
kv_namespaces = [
{ binding = "LAST_SEARCH_KV", id = "f6f608a04340492d87d3a10b0210cfa8", preview_id = "54ad69fc39bc429597e55ed0fe7acdd9" }
]
ã
ãã¨ã¯ã
await env.LAST_SEARCH_KV.get(BSKY_KV_KEY)
await env.LAST_SEARCH_KV.put(BSKY_KV_KEY, latestCreateAt)
ã®ãããªæãã§ä½¿ãã¾ãã
ã
Cron Trigger ã«ããå®æå®è¡ãè¨å®
Cloudflare Workerã§ã¯ Cron Trigger ã使ã£ã¦å®æå®è¡ãå®ç¾ã§ãã¾ãã
Cron Triggers · Cloudflare Workers docs
ã
ããã§ãwrangler.toml ã¸å®æå®è¡ã¿ã¤ãã³ã°ã®è¨å®ãè¡ãã¾ãã
ãªããã¿ã¤ã ã¾ã¼ã³ã¯ UTC ã§ãããã¨ã«æ³¨æãã¾ãã以ä¸ã®ä¾ã§ã¯ãæ¯æ¥ãæ¥æ¬æéã®åå3æã«èµ·åãã¾ãã
[triggers]
crons = [ "0 18 * * *" ]
ã
ãã¨ã¯ã scheduled
ãã³ãã©ãæã£ããªãã¸ã§ã¯ãã default export ãã¾ãã
import type { ExportedHandler } from 'cloudflare:workers'
export default {
async scheduled(_event: any, env: Env) {
const bsky = new Bsky(env)
await bsky.run()
},
} as ExportedHandler<Env>
ã
ãã¼ã«ã«ã§åä½ç¢ºèªããã«ã¯ã ringo-bsky
ã
$ wrangler dev --test-scheduled
ã«ã¦èµ·åãã¾ãã
ããã«å ããå¥ã®ã¿ã¼ããã«ãã curl
ã使ã£ã¦
$ curl "http://localhost:8787/__scheduled?cron=*+*+*+*+*"
ã®ããã«ã¢ã¯ã»ã¹ãã¾ãã
Test Cron Triggers | Cron Triggers · Cloudflare Workers docs
ã
ãã¼ã¿ç§»è¡ã«ã¤ãã¦
ã¢ããªã Google Cloud ãã Cloudflare ã¸ç§»è¡ããã®ã«ä¼´ãã
ã¨ãããã¼ã¿ç§»è¡ãå¿
è¦ã«ãªãã¾ãã
ä»åã¯
- Google Cloud Storageããããã¼ã«ã«ã®SQLiteãã¡ã¤ã«ã¨ãã¦ãªã¹ãã¢
- ãã¼ã«ã«ã®SQLiteããããã¼ã«ã«ã®D1ã¸ãã¼ã¿ããªã¹ãã¢
- ãã¼ã«ã«ã®D1ãããCloudflare D1ã¸ãªã¹ãã¢
ã¨ããã¹ãããã§ãã¼ã¿ç§»è¡ãè¡ãã¾ãã
ã
Litestreamã使ãããã¼ã«ã«ãã¡ã¤ã«ã¨ãã¦ãªã¹ãã¢ãã
Litestreamã®ããã¥ã¡ã³ãã«å¾ãã litestream restore
ã³ãã³ãã§ãã¼ã«ã«ã¸SQLiteããªã¹ãã¢ãã¾ãã
Replicating to Google Cloud Storage - Litestream
ã
ãªã¹ãã¢ããSQLiteãããã¼ã«ã«ã®D1ã¸ãã¼ã¿ãæå
¥ãã
ãã¼ã«ã«ã§ã®åä½ç¢ºèªãå¯è½ã«ãããããLitestreamã§ãªã¹ãã¢ããSQLiteããã¼ã«ã«ã®D1ã¸æå
¥ãã¾ãã
ãã¼ã¿ãæå
¥ããã¨ãã®æ¹éã¯ä»¥ä¸ã§ãã
- Cloudflareç°å¢ã§ã¯ä¸è¦ãªãã¼ã¿ããªã¹ãã¢ããªã
- Drizzle ORMã使ã£ã¦ããã¼ã«ã«ã®D1ã¸ãã¼ã¿ãæå
¥ãã
ã
ããã§ã次ã®ãããªã¹ã¯ãªãããä½æãã¾ãã
ãªãããã¼ã«ã«ã®D1ã®ãã¡ã¤ã«åãªã©ã«ã¤ãã¦ã¯ãç°å¢ã«ãã£ã¦ç°ãªãã¾ãã
@ts-ignore
import { Database } from 'bun:sqlite'
import { sql } from 'drizzle-orm'
import { drizzle } from 'drizzle-orm/bun-sqlite'
import { feeds } from '../../db/schema/feeds'
type Tweet = {
id: number
name: string
tweet: string
tweeted_at: string
tweet_id: number
}
const main = async () => {
const fromSqlite = new Database('old_data/ringo_2024_0502.db')
const fromDb = drizzle(fromSqlite)
const tweets: Tweet[] = await fromDb.all(
sql.raw('select * from tweets_tweets'),
)
const fileName =
'2073307253fd76d9e289ad074b54fc751825840a1efddf02aa13a82ecf5305f6.sqlite'
const toSqlite = new Database(
`.wrangler/state/v3/d1/miniflare-D1DatabaseObject/${fileName}`,
)
const toDb = drizzle(toSqlite)
tweets.forEach(async (t) => {
await toDb.insert(feeds).values({
name: t.name,
content: t.tweet,
createdAt: t.tweeted_at,
snsId: t.tweet_id.toString(),
})
})
console.log('finished')
}
main()
ã
ç¶ãã¦ã ringo-db
ãã£ã¬ã¯ããªã®ä¸ã§ãã¹ã¯ãªãããå®è¡ãã¾ãã
$ bun run scripts/development/import_local_db.ts
finished
ã
ãã¼ã«ã«ã®D1ã確èªããã¨ãå¿
è¦ãªãã¼ã¿ãæå
¥ããã¦ãã¾ããã
ã
ãã¼ã«ã«ã§ã®åä½ç¢ºèªãã§ããã¨ããã§ã次ã¯æ¬çªç°å¢ã§ãã
ããã§ã ringo-db
Workersãåãã¦ãããã¤ããã¨ããåæã«D1ãä½æããã¦ããã¯ãã§ãã
$ wrangler deploy --minify
...
Total Upload: 64.01 KiB / gzip: 18.33 KiB
Your worker has access to the following bindings:
- D1 Databases:
- DB: ringodb (01febb3d-148f-4f3c-8fea-e32445da1ae1)
Uploaded ringo-db (3.96 sec)
Published ringo-db (4.40 sec)
...
ã
ãã ããã®æç¹ã§ã¯D1ã¯ãããã®ã®ãã¼ãã«ãåå¨ãã¾ããã
ããã§ãwranglerã使ããæ¬çªã®D1ã«å¯¾ãã¦ãã¤ã°ã¬ã¼ã·ã§ã³ãå®è¡ãã¾ãã
https://developers.cloudflare.com/workers/wrangler/commands/#migrations-apply
$ wrangler d1 migrations apply ringodb --remote
...
Migrations to be applied:
âââââââââââââââââââââââ
â name â
âââââââââââââââââââââââ¤
â 0000_wild_pride.sql â
âââââââââââââââââââââââ
â About to apply 1 migration(s)
Your database may not be available to serve requests during the migration, continue? ⦠yes
ð Executing on remote database ringodb (01febb3d-148f-4f3c-8fea-e32445da1ae1):
ð To execute on your local development database, remove the --remote flag from your wrangler command.
ð£ Executed 2 commands in 0.4022ms
âââââââââââââââââââââââ¬âââââââââ
â name â status â
âââââââââââââââââââââââ¼âââââââââ¤
â 0000_wild_pride.sql â â
â
âââââââââââââââââââââââ´âââââââââ
ã
ãã¼ã«ã«ã®D1ãããã¼ã¿ãã¨ã¯ã¹ãã¼ããã
Cloudflareã®ä»¥ä¸ã®ããã¥ã¡ã³ããåèã«ããã¼ã«ã«ã®D1ãããã¼ã¿ãã¨ã¯ã¹ãã¼ããã¾ãã
Export an existing D1 database | Import and export data · Cloudflare D1 docs
ãªãããã¼ã«ã«ã®D1ãªãããã¨ã¯ã¹ãã¼ãæã«ã¯ --local
ãã©ã°ãå¿
è¦ã§ãã
$ wrangler d1 export ringodb --local --output=./old_data/ringodb_local_2024_0706.sql
...
ð Exporting local database ringodb (01febb3d-148f-4f3c-8fea-e32445da1ae1) from .wrangler/state/v3/d1:
ð To export your remote database, add a --remote flag to your wrangler command.
ð Exporting SQL to ./old_data/ringodb_local_2024_0706.sql...
Done!
ã
ã¨ã¯ã¹ãã¼ããããã¼ã¿ãè¦ãã¨ããããã¤ã°ã¬ã¼ã·ã§ã³æ¸ãªæ¬çªç°å¢ã§ã¯ä¸è¦ãªãã¤ã°ã¬ã¼ã·ã§ã³é¢ä¿ã®ãã¼ã¿ãå«ã¾ãã¦ãã¾ããã
ããã§ãã¨ã¯ã¹ãã¼ããããã¼ã¿ããã以ä¸ã®å
容ãåé¤ãã¾ããã
CREATE TABLE d1_migrations(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE,
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
INSERT INTO d1_migrations VALUES(1,'0000_wild_pride.sql','2024-06-17 23:22:59');
CREATE TABLE `feeds` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`name` text,
`content` text,
`created_at` text DEFAULT (CURRENT_TIMESTAMP),
`sns_id` text
);
ã
æ¬çªã®D1ã«å¯¾ãã¦ã¤ã³ãã¼ããã
次ã«ãwranglerã使ã£ã¦ããã¼ã«ã«ã¸ã¨ã¯ã¹ãã¼ããããã¼ã¿ãæ¬çªã®D1ã¸ã¤ã³ãã¼ããã¾ãã
ã¨ã¯ã¹ãã¼ããããã¼ã¿ã¯SQLãã¡ã¤ã«ã«ãªã£ã¦ããããã wrangler d1 execute
ã使ãã¾ãã
https://developers.cloudflare.com/workers/wrangler/commands/#execute
$ wrangler d1 execute ringodb --remote --file=./old_data/ringodb_local_2024_0706.sql
...
â â ï¸ This process may take some time, during which your D1 database will be unavailable to serve queries.
Ok to proceed? ⦠yes
ð Executing on remote database ringodb (01febb3d-148f-4f3c-8fea-e32445da1ae1):
ð To execute on your local development database, remove the --remote flag from your wrangler command.
Note: if the execution fails to complete, your DB will return to its original state and you can safely retry.
â ð Uploading 01febb3d-148f-4f3c-8fea-e32445da1ae1.c8499ae13caabeb9.sql
â ð Uploading complete.
â
ð Starting import...
ð Processed 751 queries.
ð£ Executed 751 queries in 0.04 seconds (2240 rows read, 1498 rows written)
Database is currently at bookmark 00000005-00000000-00004dc6-da501f7be681ab1e632fa9c002d2fc69.
ââââââââââââââââââââââââââ¬ââââââââââââ¬âââââââââââââââ¬âââââââââââââââââââââ
â Total queries executed â Rows read â Rows written â Database size (MB) â
ââââââââââââââââââââââââââ¼ââââââââââââ¼âââââââââââââââ¼âââââââââââââââââââââ¤
â 751 â 2240 â 1498 â 0.19 â
ââââââââââââââââââââââââââ´ââââââââââââ´âââââââââââââââ´âââââââââââââââââââââ
ã
ã¤ã³ãã¼ãå¾ãCloudflareä¸ã®D1ã確èªããã¨ããã¼ã¿ãæå
¥ããã¦ãã¾ããã
ã
ãã®ä»
Pagesã§ã«ã¹ã¿ã ãã¡ã¤ã³ãè¨å®
Cloudflare Pagesã§ã¯ãã¢ããªã«ã«ã¹ã¿ã ãã¡ã¤ã³ãè¨å®ã§ãã¾ãã
Custom domains · Cloudflare Pages docs
ã
ä»åã¯ä»¥ä¸ã®æµãã§å¯¾å¿ãã¾ããã
- Cloudflare Pagesã§ã®ä½æ¥
- Cloudflare Pagesã®Custom domains ãã¿ããéãã
Set up a custom domain
ãã¯ãªãã¯
- ãµããã¡ã¤ã³ã§éç¨ããã®ã§ã
ringosky.thinkami.dev
ãå
¥å
- ãã¡ã¤ã³ã®DNSã¯å¤æ´ããªãã®ã§ã My DNS providerã®
Begin CNAME setup
ãé¸æ
- Nameã¨Targetã表示ãããã®ã§ãã³ãã¼
- ãã¡ã¤ã³ã管çãã¦ãã Squarespace ã§ã®ä½æ¥
- ã«ã¹ã¿ã ã¬ã³ã¼ãã®
ã¬ã³ã¼ãã追å
ãã¯ãªãã¯ãã表示ããã¦ããå¤ãè¨å®
- å度ãCloudflareã§ã®ä½æ¥
Check DNS records
ãã¯ãªãã¯
- ãYour records for ringosky.thinkami.dev are being rechecked. Youâll be notified by email when your domain is activated.ãã¨è¡¨ç¤ºãããã®ã§ããã°ããå¾
ã¤
ã
ãã°ããå¾
ã¤ã¨ãã«ã¹ã¿ã ãã¡ã¤ã³ã§ã®éç¨ãã§ããããã«ãªãã¾ããã
ã
移è¡åã®ãã¼ã¿åé¤
Cloudflareã§éç¨ã§ããããã«ãªã£ãã®ã§ãCloud Runã§ç®¡çãã¦ãããã¼ã¿ãåé¤ãã¦ããã¾ãã
- Cloud Run
- Cloud Storage ã®ãã¹ã¦ã®ãã±ãã
- Cloud Scheduler
- ãµã¼ãã¹ã¢ã«ã¦ã³ã
- Secret Manager
- Artifact Registry
ã
ãä¸è©±ã«ãªãã¾ããããããã¨ããããã¾ããã
ã
ãã°ã« TypeError: e.env.RINGO_DB_TOTAL.calculateByName is not a function ã®ããã«è¡¨ç¤ºãããã¨ã
ä»åã
- ãã¼ã«ã«ã§ã¯ãService Binding RPC ã¾ããã¯åé¡ãªãåä½ãã¦ãã
- æ¬çªç°å¢ã«ãããã¤ããã¨ãåä½ããªã
- æ¬çªç°å¢ã®ãã°ã«ããTypeError: e.env.RINGO_DB_TOTAL.calculateByName is not a functionããåºåããã¦åä½ããªã
ã¨ãããã¨ãèµ·ãã¾ããã
ã
Service Binding RPC ã®è¨å®ã¯ãã¹ã¦ããã¥ã¡ã³ãéãè¡ãªã£ã¦ããã¯ãã§ãããããã¾ãããã¾ããã§ããã
ãããªä¸ãwrangler.toml ãè¦ãã¨ããã compatibility_date
ã®å¤ã Pages ã Workers ã®éã§å·®ç°ããããã¨ã«æ°ã¥ãã¾ããã
ã
ããã§ã compatibility_date
ã®å¤ã 2024-06-18
ã¸çµ±ä¸ããã¨ãããåä½ããããã«ãªãã¾ããã
æ¬å½ã«ãã®å¯¾å¿ã§ããã®ãèªä¿¡ã¯ããã¾ããããæå
ã§ã¯ãã®æ¹æ³ã§è§£æ±ºãããããã¡ã¢ã¨ãã¦æ®ãã¦ããã¾ãã
ã
åä½ç¢ºèª
以ä¸ã®URLã§åä½ãã¦ãã¾ããèµ·åãéããªãã¾ããã
https://ringosky.thinkami.dev/
ã
æãã¨ã®è¡¨ç¤ºã¯ãã¡ãã
https://ringosky.thinkami.dev/month
ã
Githubã«ä¸ãã¾ããã
https://github.com/thinkAmi/cf_ringo_sky