every / onEvent — refresh policies#

Declare when a source re-queries. Both builders return a RefreshPolicy ({ everyMs?, events }) for a source's refresh field.

import { source, every, onEvent } from 'janux';

sources: {
  stock: source({
    description: 'Live stock levels',
    query: ({ ctx }) => fetchStock(ctx),
    refresh: every('5m').orOn('inventory.changed'),
  }),
},

every(interval)#

every(interval: string) polls on a wall-clock interval. The string is parsed by parseDuration'300ms', '2s', '5m', '1h'.

refresh: every('30s')

.orOn(event)#

Chains an event trigger onto the interval — the source refreshes on the timer or when the event fires on the bus, whichever comes first. Chain it repeatedly for several events:

refresh: every('5m').orOn('inventory.changed').orOn('order.placed')

Each .orOn() returns a new policy (the builder never mutates), so a shared base is safe to reuse:

const slow = every('10m');

const a = slow.orOn('a.changed');   // 10m + a.changed
const b = slow.orOn('b.changed');   // 10m + b.changed — unaffected by `a`

onEvent(event)#

onEvent(event: string) is the event-only policy: no timer, refresh strictly when the event fires.

refresh: onEvent('inventory.changed')

Use it for state that only ever changes in response to something you already emit — cheaper and more precise than polling. Events come from the same bus that carries component emits, store events and server events, so a server-side mutation can invalidate a client source by name.

Related: parseDuration · Sources, effects and events · createBus