primatejs / primate

Polymorphic development platform
https://primatejs.com
MIT License
159 stars 9 forks source link

add `@primate/kv` #137

Open terrablue opened 1 week ago

terrablue commented 1 week ago
ralyodio commented 1 week ago

Here's a redis example:

import { primary } from '@primate/types';
import { createClient } from '@redis/client';
import { promisify } from 'util';

const client = createClient();

client.on('error', (err) => {
    console.error('Redis error:', err);
});

await client.connect();

const CACHE_EXPIRATION = 300; // 5 minutes in seconds

export const actions = ({ connection: db }) => {
    return {
        async getData(opts) {
            const { startDate, endDate, filter, subFilter, keyword, threatLevel, feature } = opts;

            let category;
            let where = '';

            where += ` createdAt >= "${startDate}" `;

            if (endDate) {
                where += ` AND createdAt <= "${endDate}" `;
            }

            if (filter && filter != 'All') {
                if (subFilter && subFilter !== 'All') {
                    category = `${filter} -> ${subFilter}`;
                } else {
                    category = `${filter}`;
                }

                where += ` AND categories CONTAINS $category `;
            }

            if (keyword) {
                where +=
                    ' AND string::lowercase(textContent || "") CONTAINS string::lowercase($keyword) ';
            }

            if (threatLevel && threatLevel !== 'All') {
                where += ' AND threatLevel = $threatLevel ';
            }

            if (feature) {
                where += ` AND type::point([type::number(lon), type::number(lat)]) INSIDE {
                    type: "${feature.geometry.type}",
                    coordinates: ${JSON.stringify(feature.geometry.coordinates)}
                } `;
            }

            const query = `SELECT * OMIT content, textContent FROM events ${
                where ? ' WHERE ' + where : ''
            } ORDER BY createdAt DESC`;

            const queryData = {
                category,
                keyword,
                threatLevel: parseInt(threatLevel)
            };

            const cacheKey = JSON.stringify({ query, queryData });
            const cachedData = await client.get(cacheKey);

            if (cachedData) {
                console.log('got cache: ', cacheKey);
                return JSON.parse(cachedData);
            }

            const [data] = await db.query(query, queryData);

            console.log('set cache:', cacheKey);
            await client.set(cacheKey, JSON.stringify(data), {
                EX: CACHE_EXPIRATION
            });

            return data;
        },

        async saveSearch(body) {
            const me = await db.info();

            body.createdAt = new Date().toISOString();
            body.updatedAt = new Date().toISOString();
            body.createdBy = me.id;

            const [search] = await db.create('saved_searches', body);

            return search;
        }
    };
};

export default {
    id: primary
};