db replica base
This commit is contained in:
@@ -38,7 +38,7 @@ async def get_all_rows(current_user: str = Depends(JWT.current_user)):
|
|||||||
raise HTTPException(status_code=404, detail="The user isn't found")
|
raise HTTPException(status_code=404, detail="The user isn't found")
|
||||||
@api.get("/get_user_by_email/{email}", response_model=pydentic.CreateUser)
|
@api.get("/get_user_by_email/{email}", response_model=pydentic.CreateUser)
|
||||||
async def GetUserbyEmail(email:str, current_user: str = Depends(JWT.current_user)):
|
async def GetUserbyEmail(email:str, current_user: str = Depends(JWT.current_user)):
|
||||||
user = await db.GetUserbyEmail(email)
|
user = await db.get_user_by_email(email)
|
||||||
if user:
|
if user:
|
||||||
return user
|
return user
|
||||||
else:
|
else:
|
||||||
@@ -46,18 +46,18 @@ async def GetUserbyEmail(email:str, current_user: str = Depends(JWT.current_user
|
|||||||
@api.post("/user_create", response_model=pydentic.CreateUser)
|
@api.post("/user_create", response_model=pydentic.CreateUser)
|
||||||
async def create_user(row:pydentic.CreateUser):
|
async def create_user(row:pydentic.CreateUser):
|
||||||
new_row = pydentic.CreateUser(email=row.email, description=row.description, activated = row.activated, password = row.password)
|
new_row = pydentic.CreateUser(email=row.email, description=row.description, activated = row.activated, password = row.password)
|
||||||
await db.CreateUser(new_row)
|
await db.create_user(new_row)
|
||||||
return new_row
|
return new_row
|
||||||
@api.delete("/user_delete/{email}", response_model=pydentic.CreateUser)
|
@api.delete("/user_delete/{email}", response_model=pydentic.CreateUser)
|
||||||
async def delete_user(email:str,current_user: str = Depends(JWT.current_user)):
|
async def delete_user(email:str,current_user: str = Depends(JWT.current_user)):
|
||||||
user = await db.GetUserbyEmail(email)
|
user = await db.get_user_by_email(email)
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(status_code=404, detail="The user isn't found")
|
raise HTTPException(status_code=404, detail="The user isn't found")
|
||||||
await db.DeleteUser(email)
|
await db.delete_user(email)
|
||||||
return user
|
return user
|
||||||
@api.put("/user_update/{email}", response_model=pydentic.CreateUser)
|
@api.put("/user_update/{email}", response_model=pydentic.CreateUser)
|
||||||
async def update_user(email:str, updated_row: pydentic.UserUpdate, current_user: str = Depends(JWT.current_user)):
|
async def update_user(email:str, updated_row: pydentic.UserUpdate, current_user: str = Depends(JWT.current_user)):
|
||||||
user = await db.GetUserbyEmail(email)
|
user = await db.get_user_by_email(email)
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(status_code=404, detail="The user isn't found")
|
raise HTTPException(status_code=404, detail="The user isn't found")
|
||||||
changed = False
|
changed = False
|
||||||
@@ -74,14 +74,14 @@ async def update_user(email:str, updated_row: pydentic.UserUpdate, current_user:
|
|||||||
user.password = updated_row.password
|
user.password = updated_row.password
|
||||||
changed = True
|
changed = True
|
||||||
if changed:
|
if changed:
|
||||||
await db.UpdateUser(user)
|
await db.update_user(user)
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
return user
|
return user
|
||||||
@api.post("/login")
|
@api.post("/login")
|
||||||
async def login_user(form_data: OAuth2PasswordRequestForm = Depends()):
|
async def login_user(form_data: OAuth2PasswordRequestForm = Depends()):
|
||||||
creds = pydentic.UserLogin(email=form_data.username, password=form_data.password)
|
creds = pydentic.UserLogin(email=form_data.username, password=form_data.password)
|
||||||
user = await db.LoginUser(creds)
|
user = await db.login_user(creds)
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(status_code=401, detail="The user isn't found")
|
raise HTTPException(status_code=401, detail="The user isn't found")
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ db_folder.mkdir(parents=True, exist_ok=True)
|
|||||||
db_path = db_folder / "example.db"
|
db_path = db_folder / "example.db"
|
||||||
async_engine = create_async_engine(f"sqlite+aiosqlite:///{db_path}", echo=True)
|
async_engine = create_async_engine(f"sqlite+aiosqlite:///{db_path}", echo=True)
|
||||||
#sqlite+aiosqlite — тип БД + async-драйвер ///example.db — путь к файлу (три слэша, если путь относительный; четыре, если абсолютный
|
#sqlite+aiosqlite — тип БД + async-драйвер ///example.db — путь к файлу (три слэша, если путь относительный; четыре, если абсолютный
|
||||||
|
#async_engine = create_async_engine( "postgresql+asyncpg://user:pass@host:5432/mydb", echo=True) #Можно указать Pgpool-II для psql или proxysql для mysql mariadb
|
||||||
from passlib.context import CryptContext
|
from passlib.context import CryptContext
|
||||||
#Hash password
|
#Hash password
|
||||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||||
@@ -37,13 +37,13 @@ class User(Base):
|
|||||||
async def init_db():
|
async def init_db():
|
||||||
async with async_engine.begin() as conn:
|
async with async_engine.begin() as conn:
|
||||||
await conn.run_sync(Base.metadata.create_all)
|
await conn.run_sync(Base.metadata.create_all)
|
||||||
async def CreateUser(user_info):
|
async def create_user(user_info):
|
||||||
async with AsyncSessionLocal() as session:
|
async with AsyncSessionLocal() as session:
|
||||||
new_user = User(email=user_info.email, description=user_info.description, activated=user_info.activated, password=hash_password(user_info.password))
|
new_user = User(email=user_info.email, description=user_info.description, activated=user_info.activated, password=hash_password(user_info.password))
|
||||||
session.add(new_user)
|
session.add(new_user)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
await session.refresh(new_user)
|
await session.refresh(new_user)
|
||||||
async def GetUserbyEmail(email):
|
async def get_user_by_email(email):
|
||||||
async with AsyncSessionLocal() as session:
|
async with AsyncSessionLocal() as session:
|
||||||
result = await session.execute(select(User).where(User.email==email))
|
result = await session.execute(select(User).where(User.email==email))
|
||||||
user = result.scalar_one_or_none()
|
user = result.scalar_one_or_none()
|
||||||
@@ -53,7 +53,7 @@ async def get_all_rows():
|
|||||||
result = await session.execute(select(User))
|
result = await session.execute(select(User))
|
||||||
users = result.scalars().all()
|
users = result.scalars().all()
|
||||||
return users
|
return users
|
||||||
async def UpdateUser(user_info):
|
async def update_user(user_info):
|
||||||
async with AsyncSessionLocal() as session:
|
async with AsyncSessionLocal() as session:
|
||||||
result = await session.execute(select(User).where(User.id==user_info.id))
|
result = await session.execute(select(User).where(User.id==user_info.id))
|
||||||
user = result.scalar_one_or_none()
|
user = result.scalar_one_or_none()
|
||||||
@@ -63,14 +63,14 @@ async def UpdateUser(user_info):
|
|||||||
user.activated = user_info.activated
|
user.activated = user_info.activated
|
||||||
user.password = hash_password(user_info.password)
|
user.password = hash_password(user_info.password)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
async def DeleteUser(email):
|
async def delete_user(email):
|
||||||
async with AsyncSessionLocal() as session:
|
async with AsyncSessionLocal() as session:
|
||||||
result = await session.execute(select(User).where(User.email==email))
|
result = await session.execute(select(User).where(User.email==email))
|
||||||
user = result.scalar_one_or_none()
|
user = result.scalar_one_or_none()
|
||||||
if user:
|
if user:
|
||||||
await session.delete(user)
|
await session.delete(user)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
async def LoginUser(user_info):
|
async def login_user(user_info):
|
||||||
async with AsyncSessionLocal() as session:
|
async with AsyncSessionLocal() as session:
|
||||||
result = await session.execute(select(User).where(User.email == user_info.email))
|
result = await session.execute(select(User).where(User.email == user_info.email))
|
||||||
user = result.scalar_one_or_none()
|
user = result.scalar_one_or_none()
|
||||||
|
|||||||
12
server/database/db_balancer/master.yaml
Normal file
12
server/database/db_balancer/master.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
services:
|
||||||
|
postgres-master:
|
||||||
|
image: bitnami/postgresql:16
|
||||||
|
environment:
|
||||||
|
- POSTGRESQL_REPLICATION_MODE=master
|
||||||
|
- POSTGRESQL_REPLICATION_USER=repl_user
|
||||||
|
- POSTGRESQL_REPLICATION_PASSWORD=repl_pass
|
||||||
|
- POSTGRESQL_USERNAME=admin
|
||||||
|
- POSTGRESQL_PASSWORD=admin
|
||||||
|
- POSTGRESQL_DATABASE=mydb
|
||||||
|
ports:
|
||||||
|
- '5432:5432'
|
||||||
20
server/database/db_balancer/pgpool.conf
Normal file
20
server/database/db_balancer/pgpool.conf
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#Это если вдруг мне когда нибудь приспичит сделать sql balancer с распределенными бд через pgpool-II
|
||||||
|
|
||||||
|
backend_hostname0 = 'pg-master'
|
||||||
|
backend_port0 = 5432
|
||||||
|
backend_weight0 = 1
|
||||||
|
backend_flag0 = 'ALWAYS_PRIMARY'
|
||||||
|
|
||||||
|
backend_hostname1 = 'pg-replica1'
|
||||||
|
backend_port1 = 5432
|
||||||
|
backend_weight1 = 1
|
||||||
|
backend_flag1 = 'ALLOW_TO_FAILOVER'
|
||||||
|
|
||||||
|
backend_hostname2 = 'pg-replica2'
|
||||||
|
backend_port2 = 5432
|
||||||
|
backend_weight2 = 1 #сколько запросов куда отправлять 1/1 например = 50/50
|
||||||
|
backend_flag2 = 'ALLOW_TO_FAILOVER'
|
||||||
|
|
||||||
|
load_balance_mode = on
|
||||||
|
replication_mode = off #не юзают, тк устарело и глючно
|
||||||
|
master_slave_mode = on
|
||||||
11
server/database/db_balancer/replica.yaml
Normal file
11
server/database/db_balancer/replica.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
services:
|
||||||
|
postgres-replica:
|
||||||
|
image: bitnami/postgresql:16
|
||||||
|
environment:
|
||||||
|
- POSTGRESQL_REPLICATION_MODE=slave
|
||||||
|
- POSTGRESQL_REPLICATION_USER=repl_user
|
||||||
|
- POSTGRESQL_REPLICATION_PASSWORD=repl_pass
|
||||||
|
- POSTGRESQL_MASTER_HOST=MASTER_IP_ИЛИ_DNS
|
||||||
|
- POSTGRESQL_PASSWORD=admin
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
@@ -19,14 +19,16 @@ document.getElementById('loginForm').addEventListener('submit', async function (
|
|||||||
password
|
password
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const response = await fetch('http://localhost:8000/login', {
|
const response = await fetch("http://localhost:8000/login", {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
},
|
||||||
body: JSON.stringify(userData)
|
body: new URLSearchParams({
|
||||||
});
|
username: userData.email, // ⚠️ имя поля должно быть username
|
||||||
|
password: userData.password
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
const data = await response.json(); // читаем только один раз
|
const data = await response.json(); // читаем только один раз
|
||||||
const remember_me = document.getElementById("remember").checked
|
const remember_me = document.getElementById("remember").checked
|
||||||
|
|||||||
Reference in New Issue
Block a user