Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
REDIS_PORT=6379
MEMCHACHED_PORT=11211
MEMCACHED_SERVER_URL="localhost:${MEMCACHED_PORT}"
MEMCACHED_SERVER_URL="localhost:11211"
MEMCACHED_PORT=11211
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@
"prettier/prettier": [
"error"
]
},
"parserOptions": {
"project": "./tsconfig.eslint.json"
}
}
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Supported cache storages:
- [Cache events](#cache-events)
- [Cache tags](#cache-tags)
- [Cache record TTL](#cache-record-ttl)
- [Sharable cache](#sharable-cache)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand Down Expand Up @@ -334,6 +335,45 @@ Or you can set record ttl as function parameter:
Your value will be transformed to milliseconds using time units which configured by **ttlUnits** parameter in your cache
config.

# Sharable cache
When you need to share cache between several instances you can enable sharable mode.
For enabling you should add sharable cache provider:
```json
{
"providers": [
"./providers/AppProvider",
"adonis5-cache",
"adonis5-cache/sharable-cache-provider"
]
}
```
and setup your `config/cache.ts` for using shared cache
```js
{
sharedCacheConfig: {
isSharingEnabled: true,
syncInterval: 2000
}
}
```
- isSharingEnabled - responds for enabling sharing mode for cache
- syncInterval - interval between running sync operation. Use milliseconds unit for this option


Cache synchronized via redis as transport layer. So you need to install [adonis-redis](https://www.npmjs.com/package/@adonisjs/redis/v/alpha) package for using sharable cache.
```bash
npm i @adonisjs/redis@alpha
```

For manual enabling and disabling synchronization you can call special methods on cache manager instance
```js
import CacheManager from "@ioc:Adonis/Addons/Adonis5-Cache";

CacheManager.stopSynchronization()

CacheManager.runSynchronization()
```

[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript

[typescript-url]: "typescript"
Expand Down
7 changes: 7 additions & 0 deletions adonis-typings/cache-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ declare module '@ioc:Adonis/Addons/Adonis5-Cache' {
ttlUnits: TtlUnits

enabledEvents: CacheEventsConfig
sharedCacheConfig?: SharedCacheConfig
}

interface SharedCacheConfig {
isSharingEnabled: boolean
syncInterval: number
rootNode: boolean
}
}

Expand Down
9 changes: 9 additions & 0 deletions adonis-typings/container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
declare module '@ioc:Adonis/Core/Application' {
import { CacheManagerContract } from '@ioc:Adonis/Addons/Adonis5-Cache'
import { SharableCacheManagerContract } from '@ioc:Adonis/Addons/Adonis5-SharableCache'

export interface ContainerBindings {
'Adonis/Addons/Adonis5-Cache': CacheManagerContract
'Adonis/Addons/Adonis5-SharableCache': SharableCacheManagerContract
}
}
2 changes: 2 additions & 0 deletions adonis-typings/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/// <reference path="./cache-events.ts" />
/// <reference path="./cache.ts" />
/// <reference path="./sharable-cache.ts" />
/// <reference path="./container.ts" />
27 changes: 27 additions & 0 deletions adonis-typings/sharable-cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
declare module '@ioc:Adonis/Addons/Adonis5-SharableCache' {
import { CacheManagerContract } from '@ioc:Adonis/Addons/Adonis5-Cache'

export type CacheCommand = {
method: string
args: unknown[]
isReturnThis: boolean
createdAt: string
}

export interface SharableCacheManagerContract extends Omit<CacheManagerContract, 'tags'> {
transport: SharableCacheTransportContract
runSynchronization(): void
stopSynchronization(): void
addCommandToQueue(method: string, args: unknown[], isReturnThis: boolean): void
isSharingEnabled: boolean
}

export interface SharableCacheTransportContract {
sync(cacheCommands: CacheCommand[]): void
subscribeForUpdates(handleCommands: (commands: CacheCommand[]) => Promise<void>): void
}

const SharableCacheManager: SharableCacheManagerContract

export default SharableCacheManager
}
8 changes: 4 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ services:
image: 'redis:alpine'
ports:
- $REDIS_PORT:6379
memcached:
image: 'memcached:alpine'
ports:
- $MEMCACHED_PORT:11211
memcached:
image: 'memcached:alpine'
ports:
- $MEMCACHED_PORT:11211

20 changes: 1 addition & 19 deletions japaFile.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
const { configure } = require('japa')
const { argv } = require('yargs')
const tsnode = require('ts-node')
const { iocTransformer } = require('@adonisjs/ioc-transformer')
const { files: typingsFiles } = require('./tsconfig.json')

const testFrameworkConfiguration = {
aliases: {
App: 'app',
Contracts: 'contracts',
Config: 'config',
Database: 'database',
},
}

tsnode.register({
transformers: {
after: [iocTransformer(require('typescript/lib/typescript'), testFrameworkConfiguration)],
},
files: typingsFiles,
})
require('@adonisjs/require-ts/build/register')

const { files = ['test/**/*.spec.ts'], grep } = argv
configure({
Expand Down
6 changes: 3 additions & 3 deletions npm-audit.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
integrity="sha384-wXznGJNEXNG1NFsbm0ugrLFMQPWswR3lds2VeinahP8N0zJw9VWSopbjv2x7WCvX" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.20/datatables.min.css" />
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.16.2/build/styles/atom-one-dark.min.css">
href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.3.1/build/styles/atom-one-dark.min.css">

<title>NPM Audit Report</title>
<meta name="description" content="0 known vulnerabilities found.">
Expand Down Expand Up @@ -47,15 +47,15 @@ <h5 class="card-title">
<div class="card">
<div class="card-body">
<h5 class="card-title">
3
4
</h5>
<p class="card-text">Dependencies</p>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">
February 7th 2021, 12:16:25 am
February 25th 2021, 8:28:35 pm
</h5>
<p class="card-text">Last updated</p>
</div>
Expand Down
38 changes: 19 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
"build/providers",
"build/templates",
"build/index.d.ts",
"build/index.js"
"build/index.js",
"build/sharable-cache-provider.js"
],
"adonisjs": {
"types": "adonis5-cache",
Expand Down Expand Up @@ -96,23 +97,27 @@
"dependencies": {
"dayjs": "^1.8.34",
"ms": "^2.1.2",
"ramda": "^0.27.1"
"ramda": "^0.27.1",
"uuid": "^8.3.2"
},
"peerDependencies": {
"adonis5-memcached-client": "^1.0.5",
"@adonisjs/redis": "^5.0.9",
"@adonisjs/events": "^4.0.1"
},
"devDependencies": {
"@adonisjs/ace": "^6.9.3",
"@adonisjs/core": "^5.0.4-preview-rc-2.1",
"@adonisjs/fold": "^7.0.9",
"@adonisjs/ioc-transformer": "^1.0.2",
"@adonisjs/core": "^5.0.5-canary-rc-2",
"@adonisjs/events": "^6.0.0",
"@adonisjs/logger": "^2.0.7",
"@adonisjs/mrm-preset": "^2.4.0",
"@adonisjs/mrm-preset": "^3.0.0",
"@adonisjs/redis": "^5.0.9",
"@adonisjs/require-ts": "^2.0.2",
"@poppinss/dev-utils": "^1.0.11",
"@types/node": "^14.14.9",
"@types/ramda": "^0.27.19",
"@types/chai": "^4.2.15",
"@types/memcached": "^2.2.6",
"@types/node": "^14.14.31",
"@types/ramda": "^0.27.38",
"adonis5-memcached-client": "^1.0.5",
"chai": "^4.2.0",
"commitizen": "^4.1.2",
"cpx": "^1.5.0",
Expand All @@ -121,15 +126,15 @@
"del-cli": "^3.0.1",
"doctoc": "^1.4.0",
"dotenv": "^8.2.0",
"eslint": "^7.5.0",
"eslint": "^7.20.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-adonis": "^1.0.14",
"eslint-plugin-adonis": "^1.2.1",
"eslint-plugin-prettier": "^3.1.4",
"get-port": "^5.1.1",
"github-label-sync": "^2.0.0",
"husky": "^4.2.5",
"japa": "^3.1.1",
"mrm": "^2.3.3",
"mrm": "^2.5.19",
"np": "^6.3.2",
"npm-audit-html": "^1.4.1",
"pino-pretty": "^4.1.0",
Expand All @@ -138,12 +143,7 @@
"source-map-support": "^0.5.19",
"supertest": "^4.0.2",
"ts-mockito": "^2.6.1",
"ts-node": "^8.10.2",
"typescript": "^3.9.7",
"yargs": "^15.4.1",
"@types/memcached": "^2.2.6",
"adonis5-memcached-client": "^1.0.5",
"@adonisjs/redis": "^5.0.9",
"@adonisjs/events": "^4.0.1"
"typescript": "^4.1.5",
"yargs": "^15.4.1"
}
}
65 changes: 7 additions & 58 deletions providers/AdonisCacheProvider.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,13 @@
import { IocContract } from '@adonisjs/fold/build'
import CacheManager from '../src/CacheManager'
import RedisStorage from '../src/CacheStorages/RedisStorage'
import InMemoryStorage from '../src/CacheStorages/InMemoryStorage'
import { EmitterContract } from '@ioc:Adonis/Core/Event'
import { ConfigContract } from '@ioc:Adonis/Core/Config'
import { CacheConfig, CacheManagerContract } from '@ioc:Adonis/Addons/Adonis5-Cache'
import { RedisManagerContract } from '@ioc:Adonis/Addons/Redis'
import { ContainerBindings } from '@ioc:Adonis/Core/Application'
import { AdonisMemcachedClientContract } from '@ioc:Adonis/Addons/Adonis5-MemcachedClient'
import MemcachedStorage from '../src/CacheStorages/MemcachedStorage'
import { ConstructorParams } from '@ioc:Adonis/Addons/Adonis5-Cache'
import BaseAdonisCacheProvider from './BaseAdonisCacheProvider'

export default class AdonisCacheProvider {
constructor(protected container: IocContract<ContainerBindings>) {}

public register(): void {
this.container.singleton('Adonis/Addons/Adonis5-Cache', () => {
const eventEmitter: EmitterContract = this.container.use('Adonis/Core/Event')
const config: ConfigContract = this.container.use('Adonis/Core/Config')

return new CacheManager({
eventEmitter,
config: config.get('cache'),
})
})
}

public boot(): void {
const cache: CacheManagerContract = this.container.use('Adonis/Addons/Adonis5-Cache')
const cacheConfig: CacheConfig = this.container.use('Adonis/Core/Config').get('cache')

if (cacheConfig.enabledCacheStorages.includes('redis')) {
this.registerRedisCacheStorage(cache)
}

if (cacheConfig.enabledCacheStorages.includes('in-memory')) {
this.registerInMemoryCacheStorage(cache)
}

if (cacheConfig.enabledCacheStorages.includes('in-memory')) {
this.registerInMemoryCacheStorage(cache)
}

if (cacheConfig.enabledCacheStorages.includes('memcached')) {
this.registerMemcachedCacheStorage(cache)
}
}

private registerRedisCacheStorage(cache: CacheManagerContract) {
const redis: RedisManagerContract = this.container.use('Adonis/Addons/Redis')
cache.registerStorage('redis', new RedisStorage(redis))
}

private registerInMemoryCacheStorage(cache: CacheManagerContract) {
cache.registerStorage('in-memory', new InMemoryStorage())
export default class AdonisCacheProvider extends BaseAdonisCacheProvider {
public get providerAlias(): string {
return 'Adonis/Addons/Adonis5-Cache'
}

private registerMemcachedCacheStorage(cache: CacheManagerContract) {
const memcachedClient: AdonisMemcachedClientContract = this.container.use(
'Adonis/Addons/Adonis5-MemcachedClient'
)
cache.registerStorage('memcached', new MemcachedStorage(memcachedClient))
public get cacheManagerClass(): { new (args: ConstructorParams): CacheManager } {
return CacheManager
}
}
33 changes: 33 additions & 0 deletions providers/AdonisSharableCacheProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import CacheManager from '../src/CacheManager'
import { CacheConfig, ConstructorParams } from '@ioc:Adonis/Addons/Adonis5-Cache'
import BaseAdonisCacheProvider from './BaseAdonisCacheProvider'
import SharableCacheManager from '../src/SharableCacheManager'
import { RedisManagerContract } from '@ioc:Adonis/Addons/Redis'
import { RedisCacheDistributorTransport } from '../src/SharableCacheTransports/RedisCacheDistributorTransport'

export default class AdonisSharableCacheProvider extends BaseAdonisCacheProvider {
public get providerAlias(): string {
return 'Adonis/Addons/Adonis5-SharableCache'
}

public get cacheManagerClass(): { new (args: ConstructorParams): CacheManager } {
return SharableCacheManager
}

public async boot() {
await super.boot()

const cache: SharableCacheManager = this.container.resolveBinding(this.providerAlias)

const cacheConfig: CacheConfig = this.container
.resolveBinding('Adonis/Core/Config')
.get('cache')

const redis: RedisManagerContract = this.container.resolveBinding('Adonis/Addons/Redis')
cache.setTransport(new RedisCacheDistributorTransport(redis))

if (cacheConfig.sharedCacheConfig?.isSharingEnabled) {
cache.runSynchronization()
}
}
}
Loading