Skip to content

Commit

Permalink
Merge branch 'release/0.0.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
pipisebastian committed Nov 18, 2024
2 parents 9d07957 + e7e9a2f commit dd9552a
Show file tree
Hide file tree
Showing 110 changed files with 6,799 additions and 8,072 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:

jobs:
deploy:
name: Deploy on Server
runs-on: [self-hosted, boost-was] # ๋ผ๋ฒจ์— ํ•ด๋‹นํ•˜๋Š” runner๋กœ ์‹คํ–‰

steps:
Expand All @@ -18,7 +19,7 @@ jobs:
- name: Build and Deploy Docker Images
env:
NODE_ENV: production
MONGODB_URI: ${{ secrets.MONGODB_URI }}
MONGO_URI: ${{ secrets.MONGO_URI }}
run: |
docker-compose up -d --build
Expand Down
49 changes: 40 additions & 9 deletions .github/workflows/lint_and_test.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
name: Lint and Test

on:
push:
branches:
- main
- dev
pull_request:
branches:
- main
- dev

jobs:
lint_and_test:
name: Lint and Test
lint_and_unit_test:
name: Lint and Unit Test
runs-on: ubuntu-latest

steps:
Expand All @@ -35,9 +31,44 @@ jobs:
cache: "pnpm"

# Run lint
- name: Run lint
- name: Run Lint
run: pnpm eslint .

# Run tests
- name: Run tests
# Run Unit tests
- name: Run Unit Tests
run: pnpm test
env:
JWT_SECRET: ${{ secrets.JWT_SECRET }}

test_building_docker_image:
name: Test Building Docker Image
runs-on: ubuntu-latest

steps:
# Checkout the repository
- name: Checkout Repository
uses: actions/checkout@v4

# Install Docker
- name: Install Docker
run: |
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# Install Docker Compose
- name: Install Docker Compose
run: |
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Test Building Docker Images
- name: Test Building Docker Images
env:
NODE_ENV: production
MONGO_URI: ${{ secrets.MONGO_URI }}
run: |
docker-compose build frontend backend
47 changes: 47 additions & 0 deletions .github/workflows/lint_and_unit_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Lint and Unit Test

on:
push:
branches:
- "**"

jobs:
lint_and_unit_test:
name: Lint and Unit Test
runs-on: ubuntu-latest

steps:
# Checkout the repository
- name: Checkout repository
uses: actions/checkout@v4

# Install pnpm
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 9
run_install: true

# Set up Node.js
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "pnpm"

# Run build
- name: Install dependencies and build packages
run: |
pnpm install --frozen-lockfile
pnpm --filter @noctaCrdt build
pnpm --filter server build
# Run lint
- name: Run Lint
run: pnpm eslint .

# Run Unit tests
- name: Run Unit Tests
run: pnpm test
env:
JWT_SECRET: ${{ secrets.JWT_SECRET }}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@
*/dist
/build
.DS_Store
.env
.env

# Jest globalConfig file
../globalConfig.json
124 changes: 53 additions & 71 deletions @noctaCrdt/Crdt.ts
Original file line number Diff line number Diff line change
@@ -1,129 +1,111 @@
import { LinkedList } from "./LinkedList";
import { NodeId, Node } from "./Node";
import { RemoteInsertOperation, RemoteDeleteOperation, SerializedProps } from "./Interfaces";
import { CharId, BlockId, NodeId } from "./NodeId";
import { Node, Char, Block } from "./Node";
import { RemoteDeleteOperation, RemoteInsertOperation, SerializedProps } from "./Interfaces";

export class CRDT {
export class CRDT<T extends Node<NodeId>> {
clock: number;
client: number;
textLinkedList: LinkedList;
LinkedList: LinkedList<T>;

constructor(client: number) {
this.clock = 0; // ์ด CRDT์˜ ๋…ผ๋ฆฌ์  ์‹œ๊ฐ„ ์„ค์ •
this.clock = 0;
this.client = client;
this.textLinkedList = new LinkedList();
this.LinkedList = new LinkedList<T>();
}

/**
* ๋กœ์ปฌ์—์„œ ์‚ฝ์ž… ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๊ณ , ์›๊ฒฉ์— ์ „ํŒŒํ•  ์—ฐ์‚ฐ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
* @param index ์‚ฝ์ž…ํ•  ์ธ๋ฑ์Šค
* @param value ์‚ฝ์ž…ํ•  ๊ฐ’
* @returns ์›๊ฒฉ์— ์ „ํŒŒํ•  ์‚ฝ์ž… ์—ฐ์‚ฐ ๊ฐ์ฒด
*/
localInsert(index: number, value: string): RemoteInsertOperation {
const id = new NodeId((this.clock += 1), this.client);
const remoteInsertion = this.textLinkedList.insertAtIndex(index, value, id);
const id =
this instanceof BlockCRDT
? new CharId(this.clock + 1, this.client)
: new BlockId(this.clock + 1, this.client);

const remoteInsertion = this.LinkedList.insertAtIndex(index, value, id);
this.clock += 1;
return { node: remoteInsertion.node };
}

/**
* ๋กœ์ปฌ์—์„œ ์‚ญ์ œ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๊ณ , ์›๊ฒฉ์— ์ „ํŒŒํ•  ์—ฐ์‚ฐ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
* @param index ์‚ญ์ œํ•  ์ธ๋ฑ์Šค
* @returns ์›๊ฒฉ์— ์ „ํŒŒํ•  ์‚ญ์ œ ์—ฐ์‚ฐ ๊ฐ์ฒด
*/
localDelete(index: number): RemoteDeleteOperation {
// ์œ ํšจํ•œ ์ธ๋ฑ์Šค์ธ์ง€ ํ™•์ธ
if (index < 0 || index >= this.textLinkedList.spread().length) {
throw new Error(`์œ ํšจํ•˜์ง€ ์•Š์€ ์ธ๋ฑ์Šค์ž…๋‹ˆ๋‹ค: ${index}`);
if (index < 0 || index >= this.LinkedList.spread().length) {
throw new Error(`Invalid index: ${index}`);
}

// ์‚ญ์ œํ•  ๋…ธ๋“œ ์ฐพ๊ธฐ
const nodeToDelete = this.textLinkedList.findByIndex(index);
const nodeToDelete = this.LinkedList.findByIndex(index);
if (!nodeToDelete) {
throw new Error(`์‚ญ์ œํ•  ๋…ธ๋“œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค: ${index}`);
throw new Error(`Node not found at index: ${index}`);
}

// ์‚ญ์ œ ์—ฐ์‚ฐ ๊ฐ์ฒด ์ƒ์„ฑ
const operation: RemoteDeleteOperation = {
targetId: nodeToDelete.id,
clock: this.clock + 1,
};

// ๋กœ์ปฌ ์‚ญ์ œ ์ˆ˜ํ–‰
this.textLinkedList.deleteNode(nodeToDelete.id);

// ํด๋ก ์—…๋ฐ์ดํŠธ
this.LinkedList.deleteNode(nodeToDelete.id);
this.clock += 1;

return operation;
}

/**
* ์›๊ฒฉ์—์„œ ์‚ฝ์ž… ์—ฐ์‚ฐ์„ ์ˆ˜์‹ ํ–ˆ์„ ๋•Œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
* @param operation ์›๊ฒฉ ์‚ฝ์ž… ์—ฐ์‚ฐ ๊ฐ์ฒด
*/
remoteInsert(operation: RemoteInsertOperation): void {
const newNodeId = new NodeId(operation.node.id.clock, operation.node.id.client);
const newNode = new Node(operation.node.value, newNodeId);
const NodeIdClass = this instanceof BlockCRDT ? CharId : BlockId;
const NodeClass = this instanceof BlockCRDT ? Char : Block;

const newNodeId = new NodeIdClass(operation.node.id.clock, operation.node.id.client);
const newNode = new NodeClass(operation.node.value, newNodeId) as T;
newNode.next = operation.node.next;
newNode.prev = operation.node.prev;
this.textLinkedList.insertById(newNode);
// ๋™๊ธฐํ™” ๋…ผ๋ฆฌ์  ์‹œ๊ฐ„

this.LinkedList.insertById(newNode);

if (this.clock <= newNode.id.clock) {
this.clock = newNode.id.clock + 1;
}
}

/**
* ์›๊ฒฉ์—์„œ ์‚ญ์ œ ์—ฐ์‚ฐ์„ ์ˆ˜์‹ ํ–ˆ์„๋•Œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
* @param operation ์›๊ฒฉ ์‚ญ์ œ ์—ฐ์‚ฐ ๊ฐ์ฒด
*/
remoteDelete(operation: RemoteDeleteOperation): void {
const { targetId, clock } = operation;
if (targetId) {
this.textLinkedList.deleteNode(targetId);
this.LinkedList.deleteNode(targetId);
}
// ๋™๊ธฐํ™” ๋…ผ๋ฆฌ์  ์‹œ๊ฐ„
if (this.clock <= clock) {
this.clock = clock + 1;
}
}

/**
* ํ˜„์žฌ ํ…์ŠคํŠธ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
* @returns ํ˜„์žฌ ํ…์ŠคํŠธ
*/
read(): string {
return this.textLinkedList.stringify();
}

/**
* ํ˜„์žฌ ํ…์ŠคํŠธ๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
* @returns ํ˜„์žฌ ํ…์ŠคํŠธ ๋ฐฐ์—ด
*/
spread(): string[] {
return this.textLinkedList.spread();
return this.LinkedList.stringify();
}

/**
* textLinkedList๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” getter ๋ฉ”์„œ๋“œ
* @returns LinkedList ์ธ์Šคํ„ด์Šค
*/
public getTextLinkedList(): LinkedList {
return this.textLinkedList;
spread(): T[] {
return this.LinkedList.spread();
}

/**
* CRDT์˜ ์ƒํƒœ๋ฅผ ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
* @returns ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•œ CRDT ์ƒํƒœ
*/
serialize(): SerializedProps {
serialize(): SerializedProps<T> {
return {
clock: this.clock,
client: this.client,
textLinkedList: {
head: this.textLinkedList.head,
nodeMap: this.textLinkedList.nodeMap,
LinkedList: {
head: this.LinkedList.head,
nodeMap: this.LinkedList.nodeMap,
},
};
}
}

export class EditorCRDT extends CRDT<Block> {
currentBlock: Block | null;

constructor(client: number) {
super(client);
this.currentBlock = null;
}
}

export class BlockCRDT extends CRDT<Char> {
currentCaret: number;

constructor(client: number) {
super(client);
this.currentCaret = 0;
}
}
Loading

0 comments on commit dd9552a

Please sign in to comment.