joinEntry = async (entry) => {
    const task = async () => {
      /* 1. Check if the entry is already in the log and return early if it is */
      const isAlreadyInTheLog = await has(entry.hash)
      if (isAlreadyInTheLog) {
        return false
      }

      const verifyEntry = async (entry) => {
        // Check that the Entry belongs to this Log
        if (entry.id !== id) {
          throw new Error(`Entry's id (${entry.id}) doesn't match the log's id (${id}).`)
        }
        // Verify if entry is allowed to be added to the log
        const canAppend = await access.canAppend(entry)
        if (!canAppend) {
          throw new Error(`Could not append entry:\nKey "${entry.identity}" is not allowed to write to the log`)
        }
        // Verify signature for the entry
        const isValid = await Entry.verify(identity, entry)
        if (!isValid) {
          throw new Error(`Could not validate signature for entry "${entry.hash}"`)
        }
      }

      /* 2. Verify the entry */
      await verifyEntry(entry)

      /* 3. Find missing entries and connections (=path in the DAG) to the current heads */
      const headsHashes = (await heads()).map(e => e.hash)
      const hashesToAdd = new Set([entry.hash])
      const hashesToGet = new Set([...entry.next, ...entry.refs])
      const connectedHeads = new Set()

      const traverseAndVerify = async () => {
        const getEntries = Array.from(hashesToGet.values()).filter(has).map(get)
        const entries = await Promise.all(getEntries)

        for (const e of entries) {
          hashesToGet.delete(e.hash)

          await verifyEntry(e)

          hashesToAdd.add(e.hash)

          for (const hash of [...e.next, ...e.refs]) {
            const isInTheLog = await has(hash)

            if (!isInTheLog && !hashesToAdd.has(hash)) {
              hashesToGet.add(hash)
            } else if (headsHashes.includes(hash)) {
              connectedHeads.add(hash)
            }
          }
        }

        if (hashesToGet.size > 0) {
          await traverseAndVerify()
        }
      }

      await traverseAndVerify()

      /* 4. Add missing entries to the oplog store (=to the log) */
      await oplogStore.addVerified(hashesToAdd.values())
      /* 6. Remove heads which new entries are connect to */
      await oplogStore.removeHeads(connectedHeads.values())
      /* 7. Add the new entry to heads (=union with current heads) */
      await oplogStore.addHead(entry)

      return true
    }

    return joinQueue.add(task)
  }
Join an entry into a log.

@param {module:Log~Entry} entry Entry to join with this Log

@example

await log.joinEntry(entry)

@memberof module:Log~Log
@instance