Skip to content

examples-redis

git: https://github.com/WuChenDi/Front-End/tree/master/07-nodejs/examples-redis

ts
import { Hono } from 'hono'
import { createClient } from 'redis'
import logger from './utils/logger'

const app = new Hono()

app.get('/', (c) => {
  return c.text('Hello Hono!')
})

const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))

/**
 * Redis official website: https://redis.io
 *
 * Redis JavaScript client documentation: https://redis.js.org
 */
const client = createClient({
  url: 'redis://localhost:6379',
  socket: {
    reconnectStrategy(retries) {
      if (retries > 20) {
        console.log('Too many attempts to reconnect. Redis connection was terminated')
        return new Error('Too many retries.')
      } else {
        return retries * 500
      }
    },
  },
})

client.on('ready', () => {
  logger.log('Event ready, Redis client is ready')
})

client.on('reconnecting', () => {
  logger.log('Event reconnecting, Redis client is reconnecting')
})

client.on('end', () => {
  logger.log('Event end, Redis client connection has been closed')
})

client.on('error', (error) => {
  logger.log('----- Event error, Redis client error: -----')
  logger.error(error)
})

logger.log('Before client.connect()...')

// isOpen will return False here as the client's socket is not open yet.
// isReady will return False here, client is not yet ready to use.
logger.log(`client.isOpen: ${client.isOpen}, client.isReady: ${client.isReady}`)

const connectPromise = client.connect()
// await client.connect()

logger.log('Init, After client.connect()...')

// isOpen will return True here as the client's socket is open now.
// isReady will return False here as the promise hasn't resolved yet.
logger.log(`Init, client.isOpen: ${client.isOpen}, client.isReady: ${client.isReady}`)

await connectPromise
logger.log('Init, Afer connectPromise has resolved...')

// isOpen will return True here as the client's socket is open now.
// isReady will return True here, client is ready to use.
logger.log(`Init, client.isOpen: ${client.isOpen}, client.isReady: ${client.isReady}`)

try {
  // Returns PONG
  logger.log('----- Response from PING command -----')
  logger.log(`${await client.ping()}`)
  logger.log('----- Response from PING command -----')

  // Get the time from the Redis Server.
  const serverTime = await client.time()
  logger.log('----- Server time -----')
  logger.log(serverTime)
  logger.log('----- Server time -----')

  await delay(2000)

  // Corner of Market Street (ID: 12) and 10th street (ID:27).
  // await client.pfAdd('count:sf:12:27', 'GHN34X')
  // await client.pfAdd('count:sf:12:27', 'ECN94Y')
  // await client.pfAdd('count:sf:12:27', 'VJL12V')
  // await client.pfAdd('count:sf:12:27', 'ORV87O')

  // // To get the count of Corner of Market Street (ID: 12) and 10th street (ID:27).
  // const countForMarket10thStreet = await client.pfCount('count:sf:12:27')
  // logger.log(`Count for Market Street & 10th Street is ${countForMarket10thStreet}`)
  // // Count for Market Street & 10th Street is 4.

  async function generateUniqueKey() {
    let key
    let attempts = 0
    do {
      key = Math.random().toString(36).substring(2)
      attempts++
    } while ((await client.exists(key)) && attempts < 100)
    if (attempts === 100) {
      throw new Error('Failed to generate a unique key after 100 attempts')
    }
    return key
  }

  function generateRandomValue() {
    return Math.random().toString(36).substring(2)
  }

  const defaultKey = 'key'
  const generatedKey = await generateUniqueKey()
  const targetKey = generatedKey || defaultKey
  const generatedValue = generateRandomValue()

  logger.log('targetKey:', targetKey)
  logger.log('generatedValue:', generatedValue)
  const keyExists = await client.exists(targetKey)

  if (keyExists !== 1) {
    await client.set(targetKey, generatedValue)
    // await client.set(defaultKey, generatedValue, {
    //   EX: 60,
    //   GET: true,
    // })
  }

  const targetValue = await client.get(targetKey)
  logger.log('redis value:', targetValue)

  async function getAllKeys() {
    let cursor = 0
    let keys: string[] = []

    do {
      const { cursor: nextCursor, keys: scanKeys } = await client.scan(cursor)
      cursor = nextCursor
      keys = keys.concat(scanKeys)
    } while (cursor !== 0)

    return keys
  }

  async function getAllKeyValues() {
    const keys = await getAllKeys()
    const values = await Promise.all(keys.map((key) => client.get(key)))
    const keyValuePairs = keys.reduce(
      (obj, key, index) => {
        if (values[index] !== null) {
          obj[key] = values[index] as string
        }
        return obj
      },
      {} as Record<string, string>
    )
    return keyValuePairs
  }

  const keyValuePairs = await getAllKeyValues()
  console.log(keyValuePairs)
} catch (error) {
  logger.log('----- something went wrong -----')
  logger.error(error)
  await client.quit()
}

export default app
ts
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable no-console */

const getTimestamp = () => {
  return new Date().toLocaleString() + '.' + new Date().getMilliseconds()
}

const logWithTimestamp = (message?: any, ...optionalParams: any[]) => {
  console.log(`[${getTimestamp()}]`, message, ...optionalParams)
}

const infoWithTimestamp = (message?: any, ...optionalParams: any[]) => {
  console.info(`[${getTimestamp()}]`, message, ...optionalParams)
}

const warnWithTimestamp = (message?: any, ...optionalParams: any[]) => {
  console.warn(`[${getTimestamp()}]`, message, ...optionalParams)
}

const errorWithTimestamp = (message?: any, ...optionalParams: any[]) => {
  console.error(`[${getTimestamp()}]`, message, ...optionalParams)
}

const logger = {
  log: logWithTimestamp,
  info: infoWithTimestamp,
  warn: warnWithTimestamp,
  error: errorWithTimestamp,
}

export default logger
json
{
  "scripts": {
    "dev": "bun run --hot src/index.ts"
  },
  "dependencies": {
    "hono": "^4.2.7",
    "redis": "^4.6.13"
  },
  "devDependencies": {
    "@types/bun": "latest"
  }
}