develop #14

Merged
Hare merged 4 commits from develop into master 2024-09-27 00:17:59 +09:00
11 changed files with 129 additions and 104 deletions

View File

@ -1,9 +1,11 @@
import type { Handle } from '@sveltejs/kit' import type { Handle } from '@sveltejs/kit'
import { getConnection } from '$lib/server/database/get_connection' import { getPool } from '$lib/server/database/pool';
import git from '$lib/server/git';
export const handle: Handle = async ({ event, resolve }) => { export const handle: Handle = async ({ event, resolve }) => {
const pg = getConnection(); const pg = getPool;
event.locals.db = pg; event.locals.db = pg;
event.locals.git = git;
const result = await resolve(event); const result = await resolve(event);
return result; return result;

View File

@ -1,90 +1,21 @@
// initialize import type { Postgres } from '$lib/server/database/postgres';
import type { Postgres } from '$lib/server/database'; import type { SimpleGit } from 'simple-git';
import fs from 'fs'; import fs from 'fs';
import compile from '$lib/server/article'; import compile from '$lib/server/article_compiler';
import article_git from '$lib/server/aritcle-git'; import type { TableSchema } from '$lib/server/database/table';
import server_table from '$lib/server/database/table';
import { format } from '$lib/scripts/formatted_date'; import { format } from '$lib/scripts/formatted_date';
export default async function init(db: Postgres) { const load = async (db: Postgres, git: SimpleGit) => {
await cloneRepo();
await createTable(db, [
{
name: 'article',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'id', type: 'text', constraint: 'not null' },
{ name: 'released_at', type: 'timestamp', constraint: 'not null' },
{ name: 'updated_at', type: 'timestamp', constraint: 'not null' },
{ name: 'author', type: 'text', constraint: 'not null' },
{ name: 'email', type: 'text', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' },
{ name: 'category', type: 'text', constraint: 'not null' },
{ name: 'tags', type: 'text[]', constraint: 'not null' },
{ name: 'image', type: 'text', constraint: '' },
{ name: 'publish', type: 'text', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'article_comment',
columns: [
{ name: 'id', type: 'serial', constraint: 'primary key' },
{ name: 'article', type: 'integer', constraint: 'not null' },
{ name: 'posted_at', type: 'timestamp', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'thread',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'id', type: 'text', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' },
{ name: 'category', type: 'text', constraint: 'not null' },
{ name: 'created_at', type: 'timestamp', constraint: 'not null' },
{ name: 'updated_at', type: 'timestamp', constraint: 'not null' },
{ name: 'tags', type: 'text[]', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'thread_post',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'thread_id', type: 'integer', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' },
{ name: 'posted_at', type: 'timestamp', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'thread_comment',
columns: [
{ name: 'id', type: 'serial', constraint: 'primary key' },
{ name: 'thread', type: 'integer', constraint: 'not null' },
{ name: 'posted_at', type: 'timestamp', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'tag',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'name', type: 'text', constraint: 'not null' },
{ name: 'ref_count', type: 'integer', constraint: 'not null' },
],
}
]);
const articleFiles = await crawlArticles(db); const articleFiles = await crawlArticles(db);
await db.query('update tag set ref_count = 0'); await db.query('update tag set ref_count = 0');
for (const { path, id } of articleFiles) {
console.log(`Processing ${id}...`);
await db.begin(); await db.begin();
for (const { path, id } of articleFiles) {
await db.savepoint(id);
console.log(`Processing ${id}...`);
try { try {
const gitlog = await article_git.log({ const gitlog = await git.log({
file: path.slice(11), file: path.slice(11),
strictDate: true, strictDate: true,
}); });
@ -135,36 +66,38 @@ export default async function init(db: Postgres) {
} }
} catch (err) { } catch (err) {
console.log(err); console.log(err);
await db.rollback(); await db.rollbackTo(id);
} finally { } finally {
console.log(''); console.log('');
await db.releaseSavepoint(id);
}
}
await db.commit(); await db.commit();
} }
export async function init(db: Postgres, git: SimpleGit) {
await createTable(db, server_table);
await cloneRepo(git);
await load(db, git);
} }
await db.release(); export async function reload(db: Postgres, git: SimpleGit) {
await cloneRepo(git);
await load(db, git);
} }
type ArticleFileItem = { type ArticleFileItem = {
path: string, path: string,
id: string, id: string,
} }
export type TableSchema = {
name: string,
columns: {
name: string,
type: string,
constraint: string,
}[],
}
const cloneRepo = async () => { const cloneRepo = async (git: SimpleGit) => {
if (fs.existsSync('./articles/')) { if (fs.existsSync('./articles/')) {
console.log('Pulling articles from git..'); console.log('Pulling articles from git..');
await article_git.pull(); await git.pull();
} else { } else {
console.log('Cloning articles from git..'); console.log('Cloning articles from git..');
await article_git.clone('git@gitea.hareworks.net:Hare/blog-articles.git', 'articles'); await git.clone('git@gitea.hareworks.net:Hare/blog-articles.git', 'articles');
} }
} }

View File

@ -12,12 +12,13 @@ const connectionString = `postgres://${PG_USER}:${PG_PASS}@${PG_HOST}:${PG_PORT}
let pool = new Pool({ connectionString }); let pool = new Pool({ connectionString });
export const getConnection = () => pool; export const getPool = pool;
export const reConnect = async () => { export const reConnect = async () => {
pool = new Pool({ connectionString }); pool = new Pool({ connectionString });
} }
import init_db from '$lib/server/database/init'; import { init as init_data} from '$lib/server/data_loader';
import PG from '$lib/server/database'; import PG from '$lib/server/database/postgres';
await init_db(await PG(pool)); import git from '$lib/server/git';
await init_data(await PG(pool), git);

View File

@ -24,9 +24,21 @@ export class Postgres {
await this.client!.query('commit'); await this.client!.query('commit');
} }
async savepoint(name: string) {
await this.client!.query(`savepoint ${name}`);
}
async rollback() { async rollback() {
await this.client!.query('rollback'); await this.client!.query('rollback');
} }
async rollbackTo(name: string) {
await this.client!.query(`rollback to ${name}`);
}
async releaseSavepoint(name: string) {
await this.client!.query(`release savepoint ${name}`);
}
} }
export default async ( export default async (

View File

@ -0,0 +1,77 @@
export type TableSchema = {
name: string,
columns: {
name: string,
type: string,
constraint: string,
}[],
}
export default [
{
name: 'article',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'id', type: 'text', constraint: 'not null' },
{ name: 'released_at', type: 'timestamp', constraint: 'not null' },
{ name: 'updated_at', type: 'timestamp', constraint: 'not null' },
{ name: 'author', type: 'text', constraint: 'not null' },
{ name: 'email', type: 'text', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' },
{ name: 'category', type: 'text', constraint: 'not null' },
{ name: 'tags', type: 'text[]', constraint: 'not null' },
{ name: 'image', type: 'text', constraint: '' },
{ name: 'publish', type: 'text', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'article_comment',
columns: [
{ name: 'id', type: 'serial', constraint: 'primary key' },
{ name: 'article', type: 'integer', constraint: 'not null' },
{ name: 'posted_at', type: 'timestamp', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'thread',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'id', type: 'text', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' },
{ name: 'category', type: 'text', constraint: 'not null' },
{ name: 'created_at', type: 'timestamp', constraint: 'not null' },
{ name: 'updated_at', type: 'timestamp', constraint: 'not null' },
{ name: 'tags', type: 'text[]', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'thread_post',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'thread_id', type: 'integer', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' },
{ name: 'posted_at', type: 'timestamp', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'thread_comment',
columns: [
{ name: 'id', type: 'serial', constraint: 'primary key' },
{ name: 'thread', type: 'integer', constraint: 'not null' },
{ name: 'posted_at', type: 'timestamp', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'tag',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'name', type: 'text', constraint: 'not null' },
{ name: 'ref_count', type: 'integer', constraint: 'not null' },
],
}
] as TableSchema[];

View File

@ -1,6 +1,6 @@
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
import PG from '$lib/server/database'; import PG from '$lib/server/database/postgres';
import { format } from '$lib/scripts/formatted_date'; import { format } from '$lib/scripts/formatted_date';
let data: { let data: {

View File

@ -6,9 +6,9 @@ import {
TOKEN TOKEN
} from '$env/static/private' } from '$env/static/private'
import PG from '$lib/server/database'; import PG from '$lib/server/database/postgres';
import { building } from '$app/environment'; import { building } from '$app/environment';
import init_db from '$lib/server/database/init'; import { reload as reload_data } from '$lib/server/data_loader';
export const POST: RequestHandler = async ({ url, locals }) => { export const POST: RequestHandler = async ({ url, locals }) => {
const token = url.searchParams.get('token'); const token = url.searchParams.get('token');
@ -17,6 +17,6 @@ export const POST: RequestHandler = async ({ url, locals }) => {
return error(401, 'Unauthorized'); return error(401, 'Unauthorized');
} }
if (!building) await init_db(await PG(locals.db)); if (!building) await reload_data(await PG(locals.db), locals.git);
return new Response(String(token)); return new Response(String(token));
}; };

View File

@ -1,6 +1,6 @@
import type { Article } from '$lib/article'; import type { Article } from '$lib/article';
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
import PG from '$lib/server/database'; import PG from '$lib/server/database/postgres';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
export const load: PageServerLoad = async ({ params, locals }) => { export const load: PageServerLoad = async ({ params, locals }) => {

View File

@ -1,6 +1,6 @@
import type { Article } from '$lib/article'; import type { Article } from '$lib/article';
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
import PG from '$lib/server/database'; import PG from '$lib/server/database/postgres';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
export const load: PageServerLoad = async ({ params, locals }) => { export const load: PageServerLoad = async ({ params, locals }) => {