npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cached-hafas-client

v5.1.6

Published

Pass in a HAFAS client, cache data from it.

Downloads

87

Readme

cached-hafas-client

Pass in a HAFAS client, cache data from it.

npm version ISC-licensed support me via GitHub Sponsors chat with me on Twitter

Note: This package is mainly intended to prevent expensive and/or frequent API calls to HAFAS. As a side effect, it may reduce local CPU load & latency, but that depends on the specific use case.

cached-hafas-client's core logic is separated from data storage code; You can pick the store implementation that fits your use case best. Right now the following stores are implemented:

store name | built on top of | notes -----------|-----------------|------ cached-hafas-client/stores/redis.js | Redis | cached-hafas-client/stores/sqlite.js | SQLite | TTL not implemented yet cached-hafas-client/stores/in-memory.js | in-memory (using quick-lru) |

Installation

npm install cached-hafas-client

Usage

Let's set up a cached hafas-client instance.

// create HAFAS client
import {createVbbHafas} from 'vbb-hafas'
const hafas = createVbbHafas('my-awesome-program')

// create a store backed by Redis
import Redis from 'ioredis'
import {createRedisStore} from 'cached-hafas-client/stores/redis.js'
const redis = new Redis()
const store = createRedisStore(redis)

// wrap HAFAS client with cache
import {createCachedHafasClient as withCache} from 'cached-hafas-client'
const cachedHafas = withCache(hafas, store)

Because cached-hafas-client caches HAFAS responses by "request signature", it is build on the assumption that, HAFAS works deterministically, aside from the ever-changing transit data underneath. Because there are no guarantees for this, use cached-hafas-client with a grain of salt.

This is why you must send deterministic queries; for example, you must pass opt.duration to departures()/arrivals(), so that cached-hafas-client knows the time frame that the list of results returned by HAFAS is for.

const wollinerStr = '900000007105'
const husemannstr = '900000110511'
const when = new Date(Date.now() + 60 * 60 * 1000)

// will fetch fresh data from HAFAS
await cachedHafas.departures(wollinerStr, {duration: 10, when})

// within the time frame of the departures() call above,
// so it will use the cached data
await cachedHafas.departures(wollinerStr, {
	duration: 3, when: new Date(+when + 3 * 60 * 1000)
})

Note: cached-hafas-client is only compatible with hafas-client@5.

with a custom cache TTL

By default, cached-hafas-client uses TTLs that try to strike a balance between up-to-date-ness and a cache hit ratio: The caching duration depends on how far in the future you query for.

You can pass custom cache TTLs per hafas-client method, either as static values or as a function returning the cache TTL based on the arguments.

const SECOND = 1000
const MINUTE = 60 * SECOND

const cachePeriods = {
	// cache all cachedHafas.stop(…) calls for 10m
	stop: 10 * MINUTE,
	// cache cachedHafas.trip(tripId, opt) based on sqrt(opt.when - now)
	trip: (_, opt = {}) => {
		const diffSecs = (new Date(opt.when) - Date.now()) / SECOND
		if (Number.isNaN(diffSecs)) return 10 * SECOND // fallback
		return Math.round(Math.pow(diffSecs, 1/2) * SECOND)
	},
}
const cachedHafas = withCache(hafas, store, {cachePeriods})

Counting cache hits & misses

cachedHafas.on('hit', (hafasClientMethod, ...args) => {
	console.info('cache hit!', hafasClientMethod, ...args)
})
cachedHafas.on('miss', (hafasClientMethod, ...args) => {
	console.info('cache miss!', hafasClientMethod, ...args)
})

Bypassing the cache

import {CACHED} from 'cached-hafas-client'

// will always fresh data
await cachedHafas.departures(wollinerStr, {[CACHED]: false})

tracking hits & misses as Prometheus metrics

You can optionally track the number of hits & misses as two Prometheus Counters cached_hafas_client_hits_total & cached_hafas_client_misses_total, respectively:

import {trackCachingMetrics} from 'cached-hafas-client/with-metrics.js'

trackCachingMetrics(cachedHafas) // will keep metrics now

API

createCachedHafas(hafas, storage, opt = {})

hafas must be a hafas-client@6-compatible API client.

opt overrides this default configuration:

{
	cachePeriods: {
		departures: 30_1000, arrivals: 30_1000, // 30s
		journeys: 30_1000, // 30s
		refreshJourney: 60_1000, // 1m
		trip: 30_1000, // 30s
		radar: 10_1000, // 10s
		locations: 3_600_1000, // 1h
		stop: 3_600_1000, // 1h
		nearby: 3_600_1000, // 1h
		reachableFrom: 30_1000,
	},
}

Contributing

If you have a question or need support using cached-hafas-client, please double-check your code and setup first. If you think you have found a bug or want to propose a feature, use the issues page.