Skip to content
Dannes Wessels edited this page Nov 3, 2016 · 22 revisions

Q: What is the Concurrency Model?

Single master, multi-slave.

All writes must be performed on the master, reads may be performed on the master, however you will achieve better scalability by performing all reads against slaves.

Replication concurrency is per-Collection hierarchy. There will be a single topic queue for each configured Collection.

If a slave has a collection, with a document which is under heavy-read contention, and there is a pending update for that document on the head of the topic-queue, it may be difficult to apply that update until all reads on the document have ceased, during this period replication of updates to other documents in that Collection will be blocked... Put another way: Attempting to update a specific document (via replication) which is locked for reading (on a slave), stops all replication for that collection (on the affected slave).

In future, we could possibly look at providing replication on a per-Document basis as opposed to per-Collection. Effectively, each Collection would have a fixed topic which describes adding and removing document topics, and then a number of dynamic topics for each document as they are required for updated.

Q: I have a compile error

org.exist.EXistException: org.exist.collections.triggers.DocumentTriggerProxies.add(Lorg/exist/collections/triggers/AbstractTriggerProxy;)V
	at org.exist.storage.BrokerPool.initialize(BrokerPool.java:1065)
	at org.exist.storage.BrokerPool.<init>(BrokerPool.java:722)
	at org.exist.storage.BrokerPool.configure(BrokerPool.java:248)
	at org.exist.storage.BrokerPool.configure(BrokerPool.java:224)
	at org.exist.jetty.JettyStart.run(JettyStart.java:163)
	at org.exist.jetty.JettyStart.main(JettyStart.java:71)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.exist.start.Main.invokeMain(Main.java:126)
	at org.exist.start.Main.run(Main.java:448)
	at org.exist.start.Main.main(Main.java:50)
Caused by: java.lang.NoSuchMethodError: org.exist.collections.triggers.DocumentTriggerProxies.add(Lorg/exist/collections/triggers/AbstractTriggerProxy;)V
	at org.exist.storage.BrokerPool.initialiseTriggersForCollections(BrokerPool.java:1175)
	at org.exist.storage.BrokerPool.initialize(BrokerPool.java:981)
	... 12 more

Answer: The internal Trigger interface (API) has been changed during development of eXist-db 2.2. Please update the extension-code to at least commit 15fe9259a8

Q: how to set logging visible for replication

The producer/master mainly logs on debug level unless something bad or unexpected happens. Update log4j.xml with the following lines ad documented in the FAQ.

note that for eXist-db v2.x the log4j xml system is a bit different, and the package name pattern is org.exist.replication.

Q: My queries stopped working with v0.9.0

With the v0.9.0 pre-release the java-packages have been updated making them more logical and consistent. It makes the code better maintainable. Apologies for any inconvenience.

Replication:

<trigger class="org.exist.jms.replication.publish.ReplicationTrigger">
<trigger class="org.exist.jms.replication.subscribe.ReceiverStartupTrigger">
import module namespace replication="http://exist-db.org/xquery/replication" 
              at "java:org.exist.jms.xquery.ReplicationModule"; 

Messaging:

import module namespace messaging="http://exist-db.org/xquery/messaging" 
              at "java:org.exist.jms.xquery.MessagingModule";

JMS receiver management:

import module namespace jms="http://exist-db.org/xquery/jms" 
              at "java:org.exist.jms.xquery.JmsModule";

Q: My own ActiveMQ/JMS application can not parse the messages with XML payload

For efficiency reasons (XML fragments can consume a lot of memory), the XML payload is GZIPped before transport.

To prevent compression, set 'exist.document.compression' to 'none' in the message properties of the data producer:

let $messageProperties :=
    map {
        "exist.document.compression" := "none"
    }

Q: The slave seems to think it's the master ... by why?

The log file contains the following entry: (ReplicationJmsListener.java) [onMessage]:111 - Incoming JMS message was sent by this instance. Processing stopped.

When the extension is started for the first time, the file webapp/WEB-INF/data/jms.identity is generated, containing a unique "token". With this token the extension can prevent that when a master node is also configured as a slave node, that an replication event is re-replicated.

Clone this wiki locally