Tối ưu hệ thống để xử lý dữ liệu với workers và D1 database
Hệ thống của mình tối ưu với các bước workflows : nhập thông tin xem view từ web laravel lên D1 database và frontend sẽ lấy dữ liệu đó từ workers mục đích giảm truy vấn đến backend . đối với web ít traffic thì việc này đơn giản nếu nhiều thì nó rất đáng kể . Code workers của mình :
Đầu tiên về workers : src\Service\CacheService.js
const CacheService = {
	async get(cacheKey) {
		const cache = caches.default;
		const request = new Request(`https://cache.local/${cacheKey}`);
		const response = await cache.match(request);
		if (!response) return null;
		return await response.json();
	},
	// Mặc định là 5 phút (300 giây)
	async set(cacheKey, data, maxAge = 300) {
		const request = new Request(`https://cache.local/${cacheKey}`);
		const response = new Response(JSON.stringify(data), {
			status: 200,
			headers: {
				"Content-Type": "application/json",
				"Cache-Control": `s-maxage=${maxAge}`
			}
		});
		const cache = caches.default;
		await cache.put(request, response.clone());
		return response;
	},
	async delete(cacheKey) {
		const cache = caches.default;
		const request = new Request(`https://cache.local/${cacheKey}`);
		return await cache.delete(request);
	}
}
export default CacheService;
Tiếp theo đến file : src\index.js
import CacheService from './Service/CacheService';
function getCorsHeaders(request) {
	return {
		"Access-Control-Allow-Origin": "*",
		"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
		"Access-Control-Allow-Headers": "Content-Type, Authorization", // Thêm header cụ thể hơn nếu cần
	};
}
export default {
	async fetch(request, env, ctx) {
		const url = new URL(request.url);
		const pathnames = url.pathname.split('/').filter(Boolean); // Tách phần đường dẫn thành mảng không có phần tử rỗng
		const method = request.method;
		const key = url.searchParams.get('key'); // Lấy giá trị 'key' từ query string
		// Kiểm tra nếu key không hợp lệ (nếu cần)
		// if (key !== env.KEY) {
		// 	return new Response('Yêu cầu cần key ', { status: 400 });
		// }
		// Xử lý yêu cầu có 'api' trong đường dẫn
		if (pathnames[0] === 'post') {
			const post = pathnames[1] || null; // Lấy phần thứ hai trong đường dẫn là 'post'
			if (!post) {
				return new Response('yeu cau khong hop le', { status: 400 });
			}
			const cacheKey = `views_post_${post}`; // Tạo khóa cache từ post ID
			const cacheData = await CacheService.get(cacheKey); // Kiểm tra cache
			// Nếu dữ liệu đã có trong cache
			if (cacheData) {
				return new Response(JSON.stringify({ ...cacheData, cache: "hit" }), {
					status: 200,
					headers: {
						...getCorsHeaders(request),
						"Cache-Control": "public, max-age=50", // Cài đặt cache cho response
					}
				});
			}
			// Nếu không có trong cache, truy vấn cơ sở dữ liệu
			const result = await env.DB.prepare("SELECT count FROM views WHERE postid = ?").bind(post).first();
			// Dữ liệu trả về từ DB
			let responseData = {
				...result || { status: "error", message: "Error" },
				cache: "miss"
			};
			const statusCode = result ? 200 : 404;
			// Nếu có dữ liệu, lưu vào cache
			if (result) {
				responseData = {
					...responseData,
					status: "success",
					message: "OK"
				};
				await CacheService.set(cacheKey, responseData, 20); // Lưu vào cache với thời gian sống là 20 giây
			}
			return new Response(JSON.stringify(responseData), {
				status: statusCode,
				headers: {
					...getCorsHeaders(request),
					"Cache-Control": "public, max-age=20", // Cache response
				}
			});
		}
		// Trả về mặc định nếu không phải API
		return new Response(' /post/{postid} để lấy dữ liệu view của post ');
	},
};
Tiếp theo trong file : wrangler.jsonc
/**
 * For more details on how to configure Wrangler, refer to:
 * https://developers.cloudflare.com/workers/wrangler/configuration/
 */
{
	"$schema": "node_modules/wrangler/config-schema.json",
	"name": "nhatnhat",
	"main": "src/index.js",
	"compatibility_date": "2025-04-10",
	"observability": {
		"enabled": true
	},
	"d1_databases": [
		{
			"binding": "DB",
			"database_name": "xxxxxx",
			"database_id": "588d8a1a-xxxxxx"
		}
	],
	/**
	 * Smart Placement
	 * Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
	 */
	// "placement": { "mode": "smart" },
	/**
	 * Bindings
	 * Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including
	 * databases, object storage, AI inference, real-time communication and more.
	 * https://developers.cloudflare.com/workers/runtime-apis/bindings/
	 */
	/**
	 * Environment Variables
	 * https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
	 */
	"vars": {
		"KEY": "hien123"
	},
	/**
	 * Note: Use secrets to store sensitive data.
	 * https://developers.cloudflare.com/workers/configuration/secrets/
	 */
	/**
	 * Static Assets
	 * https://developers.cloudflare.com/workers/static-assets/binding/
	 */
	// "assets": { "directory": "./public/", "binding": "ASSETS" },
	/**
	 * Service Bindings (communicate between multiple Workers)
	 * https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
	 */
	// "services": [{ "binding": "MY_SERVICE", "service": "my-service" }]
}
Sau đó bạn chỉ cần deploy dữ liệu với lệnh : npm run deploy
2 Code trên laravel :
mình cài đặt laravel với lệnh :
composer create-project laravel/laravel la12connectd1cloudfare
Ở đây mình dùng gói
composer require ntanduy/cloudflare-d1-database
Tiếp theo mình vào config : config/database.php thêm dữ liệu database vào :
 'd1' => [
            'driver' => 'd1',
            'prefix' => '',
            'database' => env('CLOUDFLARE_D1_DATABASE_ID', ''),
            'api' => 'https://api.cloudflare.com/client/v4',
            'auth' => [
                'token' => env('CLOUDFLARE_TOKEN', ''),
                'account_id' => env('CLOUDFLARE_ACCOUNT_ID', ''),
            ],
        ],
thông tin env lấy ở đây :
CLOUDFLARE_D1_DATABASE_ID=xxx-89cc-44af-b0d1-bf03942e7b2b
CLOUDFLARE_TOKEN=xxxx
CLOUDFLARE_ACCOUNT_ID=xxx
giờ đến đoạn gửi dữ liệu lên D1 trong laravel : app\Jobs\IncrementJob.php
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class IncrementJob implements ShouldQueue
{
    use Queueable;
    public int $post;
    /**
     * Create a new job instance.
     */
    public function __construct($post)
    {
        $this->post = $post;
    }
    /**
     * Execute the job.
     */
    public function handle(): void
    {
        $increment = 1;
        // Kiểm tra bản ghi đã tồn tại hay chưa
        $check = DB::connection('d1')->table('views')->where('postid', $this->post)->first();
        if (!$check) {
            // Nếu không có bản ghi nào thì tạo mới
            DB::connection('d1')->table('views')->insert([
                'postid' => $this->post,
                'count' => 1, // Tạo count ban đầu là 1
            ]);
            // Bạn có thể log hoặc xử lý ở đây
            Log::info("Created new record for postid: " . $this->post);
        } else {
            // Nếu có bản ghi thì cập nhật
            DB::connection('d1')->table('views')->where('postid', $this->post)->update([
                'count' => DB::raw('IFNULL(count, 0) + 1'), // Tăng count lên 1
            ]);
            Log::info("Cập nhật view postid: " . $this->post);
        }
    }
}
Vậy là xong hehe
 
                                    
                 
                 
                 
                