develop #14
|
@ -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;
|
||||||
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
@ -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 (
|
77
src/lib/server/database/table.ts
Normal file
77
src/lib/server/database/table.ts
Normal 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[];
|
|
@ -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: {
|
||||||
|
|
|
@ -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));
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 }) => {
|
||||||
|
|
|
@ -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 }) => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user