Wie Amplifer Logux verwendet - ein Tool für die Kommunikation zwischen Client und Server

Logux - ein Tool für die Kommunikation zwischen Client und Server


Mein Name ist Vitaliy Rizo, ich bin ein leitender Front-End-Entwickler bei Amplifer. Ich werde erläutern, wie wir Logux in einer Webanwendung verwenden: Wir organisieren den Datenaustausch in Echtzeit, Fehlerbenachrichtigungen ohne erneutes Laden der Seite, die Kommunikation zwischen Browser-Registerkarten und die Integration in Redux.


Amplifer ist ein Dienst zum Veröffentlichen in sozialen Netzwerken. Es war notwendig, Benutzer schnell und zuverlässig über Fehler zu informieren, ohne die Seite neu zu laden: Wenn es plötzlich nicht mehr möglich war, das Bild zu verarbeiten, fiel die VKontakte-API oder Facebook entschied erneut, den Beitrag nicht zu veröffentlichen. Mit Blick auf die Zukunft möchte ich sagen, dass wir auch Logux verwenden wollten, um Veröffentlichungen zu diskutieren und das Cross-Posting-Popup von RSS neu zu schreiben. Aber zuerst, warum wir mit den verfügbaren Lösungen nicht zufrieden waren.


Mögliche Lösungen: WebSocket, Firebase und Swarm.js


Normalerweise wird WebSocket verwendet, um Informationen zur automatischen Aktualisierung zu implementieren. Damit müssen Sie nicht jede Sekunde Informationsanfragen senden, wie dies bei herkömmlichen HTTP-Anfragen der Fall wäre, und die Headergröße ist gering. WebSocket hat jedoch Nachteile:


  • . , , , . , : , ;
  • , . ;
  • , , ;
  • , (CRDT), .

Firebase, , — . Firebase CRDT, Redux . CRDT Swarm.js, Redux , .


Logux


, — Logux. , Redux, CRDT . - , API-: , .


, , « ». :


imports-api.js


update (project, id, data) {
  return put(project, `settings/imports/${ id }`, convert(data))
}

imports.js


onUpdate (projectId, importId, changed) {
  return dispatch({
    projectId,
    importId,
    import: changed,
    type: 'amplifr/imports/update'
  })
}

:


imports.js


let dispatch = useDispatch()
let onUpdate = (projectId, importId, changed) => dispatch.sync({
  projectId,
  importId,
  import: changed,
  type: 'amplifr/imports/update'
}, { channels: ['imports/' + projectId] })

sync dispatch, , , . , Logux .


Logux


Neuer Fehlerabschnitt



— . , . , .


, Logux-. .


Logux Redux. Redux createStore. Logux, «» createLoguxCreator:


import { createLoguxCreator } from '@logux/redux'

let createStore = createLoguxCreator({
  credentials: loguxToken,
  subprotocol: '0.6.5',
  userId,
  server: 'wss://logux.amplifr.com'
})

let store = createStore(reducers)

store.client.start()

createLoguxCreator :


  1. . , . gon;
  2. Logux-;
  3. . , , .

Logux- , . , - posts/1, . , WebSocket.


? — , , posts/1. subscribe — :


import useSubscription from '@logux/redux/use-subscription'

let Notices = props => {
  let isSubscribing = useSubscription([`projects/${ props.id }`])

  if (isSubscribing) {
    return <Loader />
  } else {
    // Render Notices
  }
}

— , HTTP- Redux- Logux, Logux- :


def schedule_logux
  LoguxNotificationWorker.perform_async(
    { type: 'amplifr/notices/add', notice: Logux::NoticePresenter.new(notice).to_json },
    channels: ["projects/#{project.id}"]
  )
end

, . - , , . , :


import { useDispatch } from 'react-redux'

let dispatch = useDispatch()
let onNoticeHide = noticeId => dispatch.sync({
  type: 'amplifr/notices/hide',
  noticeId
}, {
  channels: [`projects/${ projectId }`]
})

, , Logux:


  • . ;
  • , ;
  • , (). -;
  • , , . , .


Verstärker aufgrund eines Fehlers im Fehlerbereich


-


Logux , . , - , . , . , , , .


Logux . «» , , localStorage. , Firefox Safari localStorage! Logux , , . , .


, , Logux , , . , , .


, Logux, .


Logux


Diskussion von Veröffentlichungen in Amplifer


, Logux, . — , :


let PostEditor = { isApprovable, postId, … } => {
  let isSubscribing = useSubscription(isApprovable ? [`posts/${ postId }`] : [])

  if (isSubscribing) {
    return <Loader />
  } else {
    // Render PostEditor
  }
}

notes :


import { useDispatch, useSelector } from 'react-redux'

let dispatch = useDispatch()
let notes = useSelector(notes.filter(note => note.postId === postId))
let onNoteAdd = note => dispatch.sync({
  type: 'amplifr/notes/add',
  note
}, {
  channels: [`posts/${ postId }`]
})

. , :


export default function notes (state = [], action) {
  if (action.type === 'amplifr/notes/add') {
    return state.concat([action.note])
  } else if (action.type === 'amplifr/posts/close') {
    return state.filter(i => i.postId !== action.postId)
  } else {
    return state
  }
}

. Logux, .



Ewiger Editor herunterladen


, @subscribe. , isSubscribing: true. , , . .


, . , squid 3, WebSocket ( Logux WebSocket). , , . — .


RSS Logux


, Logux AJAX-. , «» «» Firefox.


AJAX Logux RSS. RSS- . RSS-, .


Hostingübergreifende Einstellungen



. :


import { useDispatch } from 'react-redux'

let dispatch = useDispatch()
let onCreate = (projectId, importId, import) => {
  return dispatch.sync({
    importId,
    import,
    type: 'amplifr/imports/add'
  }, { channels: ['imports/' + projectId] })
}

let onUpdate = (projectId, importId, changed) => {
  return dispatch.sync({
    importId,
    changed,
    type: 'amplifr/imports/update'
  }, { channels: ['imports/' + projectId] })
}

, , , Logux Optimitstic UI — . , , . - , .


Beispiel für eine optimistische Schnittstelle


«» .


«», , RSS- . , . Logux (dispatch.sync(…).catch(…)), . -, , .


: catch() JSON, try { JSON.parse(…) } catch { … }. .


Logux ?


Logux WebSocket, , SPA . , . , , :


import status from '@logux/client/status'

let connected = false

status(store.client, state => {
  if (state === 'synchronized') connected = true
}

setTimeout(() => {
  if (!connected) {
    sentry.track(new Error('No Logux connection for 10 minutes'))
  }
}, 60 * 1000)

100 , . , - , :


Logux-Problemfindungsalgorithmus


, WebSocket: -, , , , , AdBlocker Kaspersky Protection. , , , Logux, .


Logux ,


Logux , . , , . RSS-, , . - , , , , .


, . — Logux. -. , , , , :


import log from '@logux/client/log'

let store = createStore(reducers)

log(store.client)

window.store = store

:


  1. RSS- ;
  2. , ;
  3. RSS-, ;
  4. ;
  5. !

:


window.store.client.log.store.created.filter(i => i[0].type === 'amplifr/popups/set')

, - : meta.tab undefined. , . , client.id client.tabId @logux/redux id tabId. , , Logux , , .


, - «» Logux, :


Logux : «? , , ?». , — , , Redux. « », , . Logux .


:


  1. Logux, Redux, CRDT ;
  2. C Logux , ;
  3. Logux , ;
  4. Logux hat seine Nachteile: Das System ist nicht einfach, es gibt immer noch Fehler und Lösungen werden nicht immer schnell gefunden.
  5. In Amplifer überwogen die Vorteile von Logux die Nachteile. Wir planen, es weiterhin bei der Umsetzung geeigneter Projekte zu verwenden.


⌘⌘⌘


Ich hoffe, Logux findet Verwendung in Ihrem Projekt. Wenn Sie Fragen haben, schreiben Sie mir bitte auf Twitter oder per Mail .


Vielen Dank an Alexander Marfitsin und Andrei Sitnik für ihre Hilfe bei der Vorbereitung dieses Artikels.


All Articles