Làm thế nào biết record được tạo ra khi nào?
Nếu bạn không có cột date nào để tự lưu thì không có cách nào để biết record đó tạo khi nào đâu nhé. Giờ chỉ có nước là tìm qua các bảng liên quan xem có chỗ nào lưu date mà phù hợp để lấy ra dùng thay thế thôi.
Kiểu như bảng user không có cột created_at (thời gian tạo) nhưng lại có một bảng activation_email_logs có cột sent_at (thời gian mail xác thực tạo tài khoản được gửi) thì có thể bê cái sent_at về làm cho created_at để chống cháy.
Hỏi về xây dựng website
Dùng luôn wordpress nha bạn.
Filter theo Quý( 3 tháng bằng 1 quý) trong react js
- Về giao diện thì em dùng mấy thư viện datepicker để build phần giao diện chọn ngày, thường thì trong các UI Library như Ant design, material ui... đều có sẵn.
- Hoặc nếu chỉ muốn xem theo quý thì em có thể để UI dạng Select > Option, một mục cho chọn năm và một mục cho chọn quý. VD: year=2022 ; quarter=Q2
- Sau đó thì gửi kèm những tham số này theo API thôi.
Về phần backend:
- Nếu gửi payload là quarter=Q2 -> quý 2 thì thêm bước chuyển đổi giá trị Q2 thành thời gian bắt đầu và thời gian kết thúc quý. Q2 thì lúc nào cũng cố định là tháng 4, 5, 6.
- Sử dụng các hàm
startOfQuartervàendOfQuartertrong các thư viện xử lý ngày tháng cho tiện - Nếu muốn lấy ra tổng số KH và tổng số giao dịch thì hãy viết một cái API mới. Dùng hàm
COUNTtrong sql để đếm và dùng where để lọc đúng quý.
Hỏi về hàm dispatch Job trong laravel
Bạn thử đặt lại tên Job xem nhé:
use App\Jobs\CreateSqlJob;
dispatch(new CreateSqlJob($databaseName, $data['company_name']));
[Rails] Tạo và quản lý jobs với dynamic thời gian chạy job và Timezone
Mình thấy cách này cũng ổn mà.
- Tạo một cái cronjob để cứ 1p / lần sẽ chạy cái một cái command của app.
- Cái command này của app sẽ check xem schedule nào thoả mãn để xử lý.
- Chỗ này bạn nên có cột
statuscho bảngschedulevà tạo index phù hợp để tối ưu cho truy vấn sql - Trong cái command, phần logic chạy cho mỗi chiến dịch quảng cáo phù hợp bạn đưa vào hệ thống queue-job. Mình sẽ scale bằng cách có nhiều queue và nhiều queue-workers.
- Nếu chưa đáp ứng được mà muốn scale hơn nữa thì bạn có thể chuyển hẳn phần chạy chíến dịch quảng cáo thành service riêng, viết bằng go hoặc rust chẳng hạn.
Bạn có thể chia sẻ thêm về vấn đề performance mà bạn đang gặp phải được không?
😭😭😭😭MỌI NGƯỜI ƠI CỨU EM, em lỡ tay bấm nhầm Undo changes:((
-
Nếu bạn chưa tạo commit cho các file đó thì không có cách nào khác để lấy lại các file đã xóa bằng git đâu. TH này chắc chỉ có nước dùng các phần mềm khôi phục file giống như trong bài này: https://www.thegioididong.com/hoi-dap/top-20-phan-mem-khoi-phuc-du-lieu-da-xoa-tren-o-cung-usb-1301314.
-
Nếu bạn đã từng tạo commit cho các file đó thì có thể khôi phục lại được về các commit đó. Bạn dùng lệnh:
git reflog -20
Nó sẽ hiện lịch sử 20 bước các sửa đổi của source code trong git. (Bỏ cái -20 cũng được). Sau đó dùng lệnh checkout để quay về phiên bản mong muốn.
Mình ví dụ như này:
> git reflog
d2a2f9a (HEAD -> fix, master) HEAD@{0}: checkout: moving from master to fix
d2a2f9a (HEAD -> fix, master) HEAD@{1}: rebase -i (finish): returning to refs/heads/master
d2a2f9a (HEAD -> fix, master) HEAD@{2}: rebase -i (squash): refactor!: remove port binding to localhost for database services
a5968d7 HEAD@{3}: rebase -i (start): checkout HEAD~2
19aa40a (origin/master, origin/HEAD) HEAD@{4}: commit (amend): feat!: traefik has been compatible with multi-projects
d90af3a HEAD@{5}: commit: feat: traefik has been compatible with multi-projects
514f3d4 (upstream/master) HEAD@{6}: clone: from git@github.com:kimyvgy-forks/docker-php-development.git
> git checkout HEAD@{5}
Làm sao để tảo một editor cho markdown giống viblo bằng nextjs?
Viblo thì sử dụng thư viện Simple MDE, ngày trước mình cũng từng trả lời một bạn câu hỏi này trên Viblo. Bạn có thể đọc lại câu trả lời của mình tại: https://viblo.asia/a/J3ZgM9xL5mB
Rất lâu về trước cũng có một bác viết bài: Làm trình soạn thảo giống Viblo. Bạn thử đọc nhé.
Ngoài ra, có nhiều editor khác cũng dùng markdown như Editor.js, Marktext. Mình khá là thích editor của Marktext, khi dùng nó rất tiện và trực quan hơi Editor hiện tại của Viblo. Đối với Marktext thì họ public editor đó tại đây: https://github.com/marktext/muya
hỏi sữa lỗi php trên byethost
Cái này là code của bạn bị lỗi. Bạn gửi code của bạn lên đây mọi người còn có thể hỗ trợ được chứ đăng cái ảnh như này thì chẳng ai có thời gian đoán mò để giúp bạn đâu.
Auth request với request body trong nginx
Không thêm được vào request body đâu bạn ạ vì nó chỉ dùng GET như bạn nói thôi. Thêm vào cái module đó nó cũng xóa bỏ.
Nhưng mà vẫn có thể truyền dữ liệu bằng cách chèn dữ liệu vào header. Bạn thử dùng header xem.
Cách tự động backup db sang một server khác
Cách 1
Một cách khá đơn giản đó là public cái port 3306 + whitelist IP cho con server chạy backup để có truy cập vào SQL server của môi trường test. Trong cái script backup thì sau khi backup thành công, bạn chạy lệnh CLI import file vào thẳng con SQL server test luôn.
Cách 2
Bạn có thể setup NFS - Network File System, giúp có thể chia sẻ file giữa các server với nhau. Khi đó thì ở server test bạn sẽ đọc được file backup.sql ở server web.
Lúc này thì bạn đặt crontab để tự động import file SQL cho môi trường test theo lịch. VD: Back up DB lúc 1h, import database vào môi trường test sẽ là 2h. Bạn áng chừng thời gian rồi để cách nhau ra như vậy là OK. Tên file SQL bạn để theo ngày tháng để khi import còn check được là có tồn tại file của ngày đó hay không nha.
hỏi về Dockerfile, docker-compose.yml
Lệnh COPY như bạn hiểu là đúng rồi nha bạn. Nó lỗi là do bạn cấu hình context là thư mục ./docker/nodejs. Docker nó sẽ chỉ tìm được các file trong thư mục này. App của bạn chứa source code ở bên ngoài nên bạn để context là thư mục gốc. Chỉ cần chỉ ra path tới file Dockerfile thôi.
Bạn sửa lại thành như này và chuyển file docker-compose.yml ra ngoài thư mục gốc nhé:
version: '3.7'
services:
app:
build:
dockerfile: ./docker/nodejs/Dockerfile
ports:
- 3000:3000
Sửa lệnh COPY:
COPY . .
hỏi frehost
Không có cái nào free đâu, host mấy web static thì may ra còn có mấy cái như dùng Github Pages, Cloudflare, Netlify...
)
hỏi mysql workbeck
Bạn dùng Xampp thì bật PHPMyadmin lên cho nhanh. Nhìn chung hai cái cũng chỉ là để access vào database mà thôi. PHPMyadmin còn dễ dùng và có UI trực quan hơn.
Còn không thì bạn tham khảo hướng dẫn này để tạo connection tới MySQL của Xampp. https://stackoverflow.com/a/59836749
Cách viblo mã hóa title
Đối với phần mã ngẫu nhiên ở phía cuối URL nó là một dạng unique ID được sinh tự động - thường gọi là hashid.
Bạn có thể dùng https://hashids.org, nó có nhiều phiên bản cho các ngôn ngữ lập trình khác nhau: C, C++, PHP, .NET, Objective-C... Bạn có thể dùng lib này để tạo mã hashid trong code. Một cách khác, nó có một bản extension để cài thêm cho PostgreSQL - cách này thì bạn không phải sửa code mà phía PostgreSQL sẽ tự động generate mã hashid cho record mới trong database.
Ngoài ra, một số package sử dụng các thuật toán mới để tạo unique ID với tốc độ cao như: nanoid, cuid. Bạn có thể đọc thêm.
Trong các sản phẩm của Viblo, Viblo sử dụng micro service nên có nhiều hình thức để tạo hashid ở từng service, ví dụ như:
- https://hashids.org
- https://github.com/vinkla/hashids
- https://github.com/paralleldrive/cuid
- https://www.npmjs.com/package/nanoid
Bạn có thể tham khảo tất cả mấy cái đó nhé.
Thắc mắc về hover trong css
Hiệu ứng này cũng khá dễ implement. Bạn sử dụng position: relative / absolute là được.
<div class="card-image-root">
<img
class="card-image"
src="https://images.unsplash.com/photo-1527004013197-933c4bb611b3?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=720&q=80"
>
<div class="card-image-overlay">
<a class="card-button" href="javascript:alert(1);">
Click me
</a>
</div>
</div>
.card-image-root {
max-width: 300px;
height: auto;
position: relative;
}
.card-image-overlay {
display: none;
border-radius: 20px;
}
.card-image {
width: 100%;
border-radius: 20px;
}
.card-image-root:hover .card-image-overlay {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: rgba(0,0,0,.8);
position: absolute;
top: 0;
left: 0;
}
.card-button {
padding: 0.5rem 1.5rem;
border-radius: 10px;
background: white;
border: none;
cursor: pointer;
color: red;
text-decoration: none;
}
Upload video max size
Cái status code của response là 0 tức là request đấy chưa gửi lên server, có nghĩa là vấn đề có thể nằm ở phía máy client. Điều này theo suy đoán của mình có thể kể đến một số khả năng:
- Kết nối internet của client không ổn định
- Vấn đề DNS không chính xác dưới máy local
- Request bị block bởi trình duyệt: do browser hoặc browser extension chẳng hạn?
- Có service worker nào đó đang xử lý việc upload gặp lỗi và cancel request hoặc đại loại thế.
Bạn thử debug theo một số hướng trên xem. Tốt nhất bạn nên cài đặt thêm công ty thu thập log như Sentry để tracing request và nắm bắt được vấn đề xem chỉ máy bạn bị hay có bao nhiêu user cũng bị giống bạn. Chứ nhiều khi bạn chủ quan test trên thiết bị cá nhân nhưng bản thân thiết bị của bạn bị lỗi chứ không phải do hệ thống.
làm sao reload api lỗi 401
Mình không dùng Angular nên cũng không rành lắm cách triển khai trong code. Bạn thử làm theo hướng dẫn sử dụng Angular Http Interceptor trong bài viết này xem nhé: https://www.bezkoder.com/angular-12-refresh-token/
import { HTTP_INTERCEPTORS, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { TokenStorageService } from '../_services/token-storage.service';
import { AuthService } from '../_services/auth.service';
import { BehaviorSubject, Observable, throwError } from 'rxjs';
import { catchError, filter, switchMap, take } from 'rxjs/operators';
// const TOKEN_HEADER_KEY = 'Authorization'; // for Spring Boot back-end
const TOKEN_HEADER_KEY = 'x-access-token'; // for Node.js Express back-end
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private tokenService: TokenStorageService, private authService: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<Object>> {
let authReq = req;
const token = this.tokenService.getToken();
if (token != null) {
authReq = this.addTokenHeader(req, token);
}
return next.handle(authReq).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && !authReq.url.includes('auth/signin') && error.status === 401) {
return this.handle401Error(authReq, next);
}
return throwError(error);
}));
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
const token = this.tokenService.getRefreshToken();
if (token)
return this.authService.refreshToken(token).pipe(
switchMap((token: any) => {
this.isRefreshing = false;
this.tokenService.saveToken(token.accessToken);
this.refreshTokenSubject.next(token.accessToken);
return next.handle(this.addTokenHeader(request, token.accessToken));
}),
catchError((err) => {
this.isRefreshing = false;
this.tokenService.signOut();
return throwError(err);
})
);
}
return this.refreshTokenSubject.pipe(
filter(token => token !== null),
take(1),
switchMap((token) => next.handle(this.addTokenHeader(request, token)))
);
}
private addTokenHeader(request: HttpRequest<any>, token: string) {
/* for Spring Boot back-end */
// return request.clone({ headers: request.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + token) });
/* for Node.js Express back-end */
return request.clone({ headers: request.headers.set(TOKEN_HEADER_KEY, token) });
}
}
export const authInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
];
laravel không chạy
Bạn dùng Nginx hay Apache, bạn check lại config của hai cái đó xem, có thể bạn chưa trỏ root của web server vào thư mục /public.
Nhờ mọi người tư vấn về remote
dùng git để car team làm việc(mới tìm hiểu sơ sơ)
=> Bạn có thể tham khảo Git flow mình chia sẻ trong bài này: https://viblo.asia/p/slide-chia-se-ve-git-workflow-cac-van-de-thuong-gap-mot-so-rule-nen-co-khi-tao-pull-request-E375z4BjZGW. Trong đó thì Git flow sẽ chia branch và các rule đi kèm giúp tránh/giải quyết việc conflict (xung đột code khi nhiều người cùng sửa một file).
git chỉ có thể truy cập được từ máy công ty
=> Việc này mình nghĩ là cân thiết quá đến mức đấy và rất khó để control. Nếu để chỉ code được ở máy công ty cũng sẽ có nhiều bất cập. Giả sử phải làm remote do dịch bệnh sẽ khó mà kiểm soát được, trong khi xu hướng hiện nay là làm việc linh hoạt. Hoặc đơn giản nhất là dev làm chưa kịp deadline muốn về nhà làm tiếp thì làm sao. Dù bạn có setup hệ thống kiểu gì thì mấu chốt ở đây là con người, khi dev muốn kéo code về vẫn hoàn toàn có thể. Đơn giản là Dev sẽ push lên repo cá nhân của họ rồi về ở nhà thì kéo code từ repository cá nhân về là by pass được. Thế nên chỉ cần có rule cho team là ký điều khoản bảo mật cho dự án trong đó quy định không được public repo, không được lưu trữ dữ liệu về thiết bị cá nhân khi chưa được phê duyệt.
setup các máy tính của dev trong công ty để họ có thể làm remote
=> Cái này khi dùng git thì họ sẽ có private key / public key để sử dụng. Tuân thủ theo Git flow ở mục đầu là OK rồi. Bạn có thể tìm hiểu và setup CI/CD để tự động deploy nữa là OK.
Làm thế nào để api gateway gọi tới 2 service cùng lúc trong microservices
E muốn hỏi là khi muốn thực hiện một số chức năng ở bên account service mà cần đăng nhập mới thực hiện được, thì cần làm thế nào để check access token ở bên authen trước, nếu access token ko hợp lệ thì ko cần gọi bên account-service nữa ạ.
Cái này của bạn là logic của ứng dụng. Nginx là reverse proxy nên không đảm nhiệm xử lý này. Cái này bạn viết trong code của service cần làm thôi.
Vì em thấy nginx chỉ giống kiểu đặt cấu hình chứ không thấy nhận dữ liệu trả về từ api được, và cũng không thấy gọi được 2 service trong cùng 1 endpoint
Đúng rồi bạn, Nginx chỉ đảm nhiệm là điều hướng request vào service phụ trách. VD: http://account.example.lc => Account Service | http://auth.example.lc => Auth Service.





