Sonatype Nexus (3.12) が orientdb が壊れたとかで起動しなくなったら

## ディスクフルでNexus (3.12)が死ぬと...

☠　再起動時にこういうエラーを吐いて死にます ☠

```
nexus_1  | 2018-08-07 02:21:36,632+0000 ERROR [FelixStartLevel] *SYSTEM org.sonatype.nexus.extender.NexusContextListener - Failed to start nexus
nexus_1  | com.orientechnologies.orient.core.exception.OStorageException: Cannot open local storage '/nexus-data/db/config' with mode=rw
nexus_1  |      DB name="config"
nexus_1  |      at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.open(OAbstractPaginatedStorage.java:323)
nexus_1  |      at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.open(ODatabaseDocumentTx.java:259)
nexus_1  |      at org.sonatype.nexus.orient.DatabaseManagerSupport.connect(DatabaseManagerSupport.java:143)
nexus_1  |      at org.sonatype.nexus.orient.DatabaseInstanceImpl.doStart(DatabaseInstanceImpl.java:56)
nexus_1  |      at org.sonatype.goodies.lifecycle.LifecycleSupport.start(LifecycleSupport.java:104)
nexus_1  |      at org.sonatype.goodies.lifecycle.Lifecycles.start(Lifecycles.java:44)
nexus_1  |      at org.sonatype.nexus.orient.DatabaseManagerSupport.createInstance(DatabaseManagerSupport.java:252)
nexus_1  |      at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
nexus_1  |      at org.sonatype.nexus.orient.DatabaseManagerSupport.instance(DatabaseManagerSupport.java:231)
nexus_1  |      at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
nexus_1  |      at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
nexus_1  |      at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
nexus_1  |      at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
nexus_1  |      at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
nexus_1  |      at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
nexus_1  |      at java.util.concurrent.ForkJoinTask.doInvoke(ForkJoinTask.java:401)
nexus_1  |      at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:734)
nexus_1  |      at java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:160)
nexus_1  |      at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:174)
nexus_1  |      at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
nexus_1  |      at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
nexus_1  |      at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:583)
nexus_1  |      at org.sonatype.nexus.orient.restore.RestoreServiceImpl.doStart(RestoreServiceImpl.java:76)
nexus_1  |      at org.sonatype.nexus.common.stateguard.StateGuardLifecycleSupport.start(StateGuardLifecycleSupport.java:67)
nexus_1  |      at org.sonatype.nexus.common.stateguard.MethodInvocationAction.run(MethodInvocationAction.java:39)
nexus_1  |      at org.sonatype.nexus.common.stateguard.StateGuard$TransitionImpl.run(StateGuard.java:191)
nexus_1  |      at org.sonatype.nexus.common.stateguard.TransitionsInterceptor.invoke(TransitionsInterceptor.java:56)
nexus_1  |      at org.sonatype.nexus.extender.NexusLifecycleManager.startComponent(NexusLifecycleManager.java:155)
nexus_1  |      at org.sonatype.nexus.extender.NexusLifecycleManager.to(NexusLifecycleManager.java:95)
nexus_1  |      at org.sonatype.nexus.extender.NexusContextListener.frameworkEvent(NexusContextListener.java:189)
nexus_1  |      at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1429)
nexus_1  |      at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308)
nexus_1  |      at java.lang.Thread.run(Thread.java:748)
nexus_1  | Caused by: java.lang.NullPointerException: null
nexus_1  |      at com.orientechnologies.orient.core.storage.impl.local.paginated.wal.ODiskWriteAheadLog.cutTill(ODiskWriteAheadLog.java:919)
nexus_1  |      at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.makeFullCheckpoint(OAbstractPaginatedStorage.java:3705)
nexus_1  |      at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.recoverIfNeeded(OAbstractPaginatedStorage.java:3936)
nexus_1  |      at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.open(OAbstractPaginatedStorage.java:288)
nexus_1  |      ... 32 common frames omitted
```

内部的に使っている [OrientDB](https://orientdb.com/) というJava製の組み込みグラフDB、特に `config` テーブルが壊れているのが原因と思われます。（スタックトレースにテーブル名は出ています）

## 壊れた OrientDB を復活させる

前述のスタックトレースがなくなるまで、 下記の作業を繰り返します。

1. OrientDBのテーブル(`nexusのルート/db/テーブル名` のディレクトリ)に接続
2. エクスポート
3. テーブルの削除
4. テーブルの再作成
5. 2で作成したファイルのインポート

### orient-console を立ち上げる

今回は [DockerにNexusを立てている](https://github.com/cavemandaveman/nexus) ので下記コマンドでOrientDBに接続しますが、自分で nexus-orient-console.jar 相当を手に入れてもいいと思います。（どうせポートではなくファイルシステム相手につなぎに行くのでDockerの内外はあまり関係ない。）

```console
$ docker-compose run --rm nexus sh
$ java -jar ./lib/support/nexus-orient-console.jar

# or 
# $ docker-compose run --rm nexus java -jar ./lib/support/nexus-orient-console.jar
```

### テーブルを再作成

コンソールに入ったら、たとえば `analytics` テーブルを再作成する場合は、下記コマンドを実行します。

```
CONNECT 'plocal:/nexus-data/db/analytics' admin admin
EXPORT DATABASE analytics-export
DROP DATABASE
CREATE DATABASE 'plocal:/nexus-data/db/analytics'
IMPORT DATABASE analytics-export.json.gz
DISCONNECT
```

（コンソールを抜けるには `exit`)

私の場合は、下記テーブルの再作成が必要でした。

- analytics
- config
- component
- accesslog

うち、一部テーブルについては、直接上記手順を実施するとCONNECTの時点で怒られるので、DBのディレクトリ自体を別名にコピー等してから実施しました。

## 無事

起動しました！

```console
nexus_1  | 2018-08-07 03:15:12,209+0000 INFO  [jetty-main-1] *SYSTEM org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@1897e027{HTTP/1.1,[http/1.1]}{0.0.0.0:8081}
nexus_1  | 2018-08-07 03:15:12,210+0000 INFO  [jetty-main-1] *SYSTEM org.eclipse.jetty.server.Server - Started @28203ms
nexus_1  | 2018-08-07 03:15:12,210+0000 INFO  [jetty-main-1] *SYSTEM org.sonatype.nexus.bootstrap.jetty.JettyServer -
nexus_1  | -------------------------------------------------
nexus_1  | Started Sonatype Nexus OSS 3.12.1-01
nexus_1  | -------------------------------------------------
```


## リンク

- https://stackoverflow.com/questions/42951710/orientdb-corruption-state-in-nexus-repository-version-3-2-0-01