What I built
Simple Javascript library to manage asynchronous cache/storage in app/service.
Category Submission:
The best category matches my project is Wacky Wildcards
App Link
You can find library page and package here - Async Cache Service on NPM
Screenshots
Description
The asynchronous cache service is designed to handle the storage and retrieval of data in a non-blocking manner. When data is being loaded into the cache, the service returns a Promise object to the requester. This Promise serves as a placeholder or notification that the data is currently in the process of being fetched.
Once the data loading process is complete and the data is successfully retrieved, the cache service resolves all previously issued Promises associated with that specific data. By resolving the Promises, the cache service effectively provides the updated and complete data to all subscribers or requesters who were waiting for it.
How to use
Typescript Example:
import { AsyncCacheService } from 'async-cache-service';
// by default - the cache is never expire
const cacheService = new AsyncCacheService<string>();
// with 5min expiration
const cacheService = new AsyncCacheService<string>(300_000);
// as a dependency with 15min expiration
export class SomeDataService {
constructor(private cacheService = new AsyncCacheService<string>(900_000)) {}
}
Javascript Example:
import {AsyncCacheService} from 'async-cache-service';
class DataService {
// cache expires in 15min
constructor(cacheService = new AsyncCacheService(15 * 60 * 1000)) {
this.cacheService = cacheService;
}
async getData(id) {
if (this.cacheService.isExpired(id) {
this.cacheService.refreshItem(id);
try {
// retrieve data from somewhere
const data = await axios.get('/some/resource');
this.cacheService.setItem(id, data);
} catch (e) {
this.cacheService.flushItem(id);
}
}
return this.cacheService.getItem(id);
}
}
When the getData method of DataService is called, it returns a Promise, and DataService initiates the data load. During this process, all incoming calls to getData will receive Promises that resolve after the data load. In other words, we eliminate the necessity to have a well-known isLoading flag in our DataService and provide an elegant way to handle multiple data requests.
Link to Source Code
You can find library sources here - Async Cache Service on Github
Permissive License
This project is under MIT License
Background (What made you decide to build this particular app? What inspired you?)
In the preceding article Vanilla JS data cache service, I emphasized the issue of asynchronous data cache and outlined a potential solution. However, after thoughtful consideration, I opted to integrate the suggested approach into a compact Javascript library, accompanied by comprehensive unit tests and leveraging Github Actions for complete CI/CD workflow - encompassing build -> test -> package -> deploy. The resultant library, named "async-data-service", introduces an efficient method to manage asynchronous cache/storage operations with minimal developer overhead.
How I built it (How did you utilize GitHub Actions or GitHub Codespaces? Did you learn something new along the way? Pick up a new skill?)
Well, I used TypeScript (love it!) and Rollup for bundling. For my projects, I prefer to use the Nx build systemit provides me with a lot of pre-defined tools and allows me to focus on what I do. For unit tests, I used the Jest framework. The real challenge for me in this project was to utilize GitHub Actions for NPM publishing.
The most available resources describe the publishing process in a pretty straightforward way, like (taken from official :
name: Publish Package to npmjs
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v3
with:
node-version: '16.x'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Which isn't really helpful. How does "npm ci" relate to "npm publish"? What is the difference between a "published" release and a "created" release? And finally, where are my built artifacts?
So, I need to find answers. The first thing I resolved was the question regarding the difference between "created" and "published" events for releases. Actually, the "created" event is emitted only for draft releases, while the "published" event is emitted for non-draft releases. Therefore, I will use the "published" event in my Github Actions.
Next, I have to consider that Nx puts build artifacts into the "dist/packages/async-cache-service" folder. Therefore, I need to run "npm publish" from there. As a result of my GitHub Actions efforts, I implemented two actions - "push" and "publish".
The "push" action is used to handle the push event of a pull request and performs the build and test of the proposed changes:
name: Node.js CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm test
The "publish" action is used to handle the release publish event and performs the build, test, and publish steps for the release in two steps:
name: Publish Package to npmjs
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: |
npm ci
npm run build --if-present
npm test
- name: Archive production artifacts
uses: actions/upload-artifact@v3
with:
name: artifact
path: dist/packages/async-cache-service
download:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download build step artifact
uses: actions/download-artifact@v3
with:
name: artifact
- uses: actions/setup-node@v3
with:
node-version: '18.x'
registry-url: 'https://registry.npmjs.org'
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
As you can see, this action contains two steps - build and publish. The build step performs the build, test, and stores the build artifacts into the Github storage. The publish step retrieves the just created build from the build node and publishes it into the NPM registry.
In summary, I find myself very interested in using GitHub Actions for my current and future projects. I love the way it works. My next step is to adopt GitHub Actions for another project I'm working on, written in C.
Top comments (0)