Skip to content

Instantly share code, notes, and snippets.

@smukkejohan
Created June 1, 2022 14:58
Show Gist options
  • Save smukkejohan/2515bfa537cd63492f84ddad5e241491 to your computer and use it in GitHub Desktop.
Save smukkejohan/2515bfa537cd63492f84ddad5e241491 to your computer and use it in GitHub Desktop.
Persistent store with events
import Redis from "ioredis";
import EventBus from 'js-event-bus';
//import { persistBus } from './routes/admin/_persist-bus';
let bus = EventBus();
const redisConfig = {
segment: 'nyhedshjul'
}
if(process.env.REDIS_SENTINELS && process.env.REDIS_SENTINELS.indexOf(';') > 0){
// a string stariting with the name of the group, a semicolon, followed by sentinels in the format host:port, seperated by commas:
// "name;sentinel_one:1234,sentinel_two:1234, ... "
let REDIS_SENTINELS = process.env['REDIS_SENTINELS'];
redisConfig.name = REDIS_SENTINELS.split(';')[0];
redisConfig.sentinels = REDIS_SENTINELS.split(';')[1].split(',').map( function(s){
let parts = s.split(':')
return {host: parts[0].trim(), port: parseInt(parts[1].trim())}
})
} else if(process.env.REDIS_HOST){
redisConfig.host = process.env.REDIS_HOST
} else {
redisConfig.host = 'nyhedshjul_redis_1' // default
}
export const client = new Redis(redisConfig) // set and subscribe needs individual redis clients
export const subscribeSet = () => {
const keySubsriber = new Redis(redisConfig)
keySubsriber.config('set','notify-keyspace-events','KEA')
keySubsriber.subscribe('__keyevent@0__:set', 'nyhedsjul:*')
//keySubsriber.subscribe('nyhedsjul')
keySubsriber.on('message', async function(keyevent, key) {
const value = await client.get(key)
//bus.emit('sse', null, 'redis', {key: key, value: value} )
bus.emit('sse', null, key, {key: key, value: value} )
});
return keySubsriber;
}
//keySubsriber.subscribe('nyhedsjul')
/*persistBus.on(`persist.*`, function (val) {
console.log(`Inside persist.${key} event bus message`, val);
//store.set(val)
});*/
/*keySubsriber.on('message', function(key, _val) {
const val = JSON.parse(_val)
// do what you want when a value is updated
console.log("redis sub");
console.log(val.key, val.value);
console.log("event name is", `persist.${val.key}`)
bus.emit('sse', null, `persist.${val.key}`, val.value)
bus.emit('sse', null, `test`, 0)
});*/
// you can target a specific key with a second parameter
// example, client_redis.subscribe('__keyevent@0__:set', 'mykey')
//export default redisConfig ? new Redis(redisConfig) : new Redis();
<script>
import {
config
} from '../config';
import NewsItem from './NewsItem.svelte';
import { transitionInStore, transitionOutStore } from '../stores'
import { onMount, onDestroy } from 'svelte';
onMount(async () => {
const es = new EventSource('/stream')
transitionInStore.sseRedis(es)
transitionOutStore.sseRedis(es)
});
export let articles = [];
export let refreshing = true;
//export let visible = false;
$ : inSeconds = $transitionInStore
$ : outSeconds = $transitionOutStore
</script>
<style lang="less">
.NewsArticles {
flex-direction:row;
display:flex;
justify-content: space-around;
align-items: stretch;
width: 100%;
height: 100%;
will-change: transform;
transform:translate(0,0);
transform-origin: left top;
transition: cubic-bezier(0.2, 0, 0.4, 1) var(--transitionIn) transform;
transition-duration: var(--transitionIn);
transition-delay:0s;
background-color: var(--backgroundColor);
&.refreshing {
transition-duration: 0s;
transition-delay: var(--transitionOut);
transform:translate(100%,0);
}
}
.wipe {
background: linear-gradient(to right, rgba(0,0,0,0) 50%, var(--backgroundColor) 50.25%);
background-size: 203% 100%;
background-position:left;
position:absolute;
width:50%;
height:100%;
display:block;
&.refreshing {
transition: var(--transitionOut) cubic-bezier(0.5, 0, 0.5, 1);
background-position:right;
}
}
</style>
<div class="wipe refreshing" style="--backgroundColor:{config.design.NewsItem.wipe.backgroundColor};--transitionIn:{inSeconds}s;--transitionOut:{outSeconds}s;">
</div>
<div class="NewsArticles" class:refreshing style="--backgroundColor:{config.design.Strip.backgroundColor};--transitionIn:{inSeconds}s;--transitionOut:{outSeconds}s;">
{#each articles as content (content.urn)}
<NewsItem {...content}>
</NewsItem>
{/each}
</div>
<div class="wipe" class:refreshing style="--backgroundColor:{config.design.NewsItem.wipe.backgroundColor};--transitionIn:{inSeconds}s;--transitionOut:{outSeconds}s;">
</div>
import { writable, get } from 'svelte/store'
import { config } from './config'
const { transition } = config.design.NewsItem.wipe
const prefix = 'nyhedsjul'
const persistentWritable = (key, defaultValue) => {
const { subscribe, set, update } = writable(defaultValue);
//console.debug("Set default value:", defaultValue)
let _redisValue = undefined;
const store = {
subscribe,
update,
set,
sseRedis: (eventSource) => { // Call in onMount to receive updates to store from sse when changed in redis
eventSource.addEventListener(key, async (e) => {
const data = JSON.parse(e.data)
const val= get(store)
//console.debug("redis set event", data.value)
//console.debug(val)
_redisValue = data.value
if(val != data.value) {
//console.log("value changed setting")
set(data.value)
}
});
},
useRedis: async (fetch) => { // Call in preload to setup store as redis backed
const redisResponse = await fetch(`/admin/persist-${key}`)
if(redisResponse.ok) {
//console.log("Found in redis set inital")
const json = await redisResponse.json()
_redisValue = json.value
const val= get(store)
if(val != _redisValue) {
set(_redisValue)
}
}
subscribe(async (current) => {
if(_redisValue != current) {
//console.debug("useRedis subsriber set from interface push to redis", current)
await fetch(`/admin/persist-${key}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({value: current}),
});
} /*else {
console.debug("useRedis subsriber set from redis, do nothing", current)
}*/
});
}
}
return store
};
export const transitionInStore = persistentWritable(`${prefix}:wipeinseconds`, transition.in);
export const transitionOutStore = persistentWritable(`${prefix}:wipeoutseconds`, transition.out);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment