この記事を作った動機

 2026/9/9 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。

次に軽くやりたいことを記述

  • コントローラープロセス間のファイル書き込み衝突を回避する実装
  • Core拡張機能と、コントローラーにおいて、設定を伝搬するように実装
  • 拡張モジュールにmainSysから共通で提供する関数(インターフェース)を引数として辞書型などにまとめ、モジュールに渡して呼び出せるようにする
  • コントローラーのログを見えるように、マルチプロセッシングに関して調べる
  • コントローラー間をマルチプロセッシングライブラリのIPC実装でつなげる
  • pexpect の端末セッションや、マルチプロセッシングで独立したプロセスとして動くプロセスのそれぞれの出力は、独立したターミナルを立ち上げるようにする。GUI環境であれば、GUIのインストールされているターミナルエミュレーターを複数起動し、それぞれのセッションやプロセスに端末を1つずつ割り当て、ログの可読性向上を図る。
  • 拡張機能を読み込み終わったあと、依存関係に関して不足がないか確認する処理を導入する。具体的には各拡張機能の依存関係リストに対して、読み込んだ拡張機能を線形探索で単純にそれぞれ照合して不足がないか確認する。
  • 卒論の試作物から、フロントエンドをコピーしてきて、今回の試作物の DataServer の動作検証ができるように改変する。Core拡張機能の呼び出し名に対応させ、割り込みとコマンドに関して、それぞれが独立してwebsocket接続を持つようにする。

やったことの詳細

DataServer の起動オプションを追加

 DataServer について、拡張機能を読み込むだけの動作と、読み込んだ拡張機能をもとに、DataServer を起動させようとすることを分けてユーザーが明示してそれぞれ操作できるようにするために、argparseライブラリによって以下のようになるように実装した。

 以下は、argparseに関する実装が正しくできたかテストした様子である。引数に対してどう動作するか確かめたかったので、実際に拡張機能を読み込んだり、DataServer を起動する機能は一時的にコメントアウトしてテストした。何も出力がターミナルに出ていないとき、引数が受理され、正常に動作したことを示す。

python main.py --loadExtension 
# 何も出力しない
python main.py --startServer
# 何も出力しない
python main.py --loadExtension --startServer
#--loadExtension and --startServer cannot be set at the same time.

python main.py --loadExtension aaa 
#usage: main.py [-h] [--loadExtension] [--startServer]
#main.py: error: unrecognized arguments: aaa

Core 拡張機能の機能を一時的に制限

 卒論で書いた試作物のフロントエンドと今回試作している DataServer 間で一旦動作を確認したいため、すでに実装がある程度できており、卒論時点で動いていたモジュールに限定して動作するように実装を変更した。

変更前
{
    "name": "Core",
    "UUID": "589fe65d-639c-42a3-b395-fca2143afd75",
    "description": "Manage notebook and pages. Provide basic notebook interface.",
    "frontend":{
        "modules": []
    },
    "DataServer":{
        "CommandModules":[
            "backend/commands/info.py",

            "backend/commands/notebookAndPage/createNotebook.py",
            "backend/commands/notebookAndPage/deleteNotebook.py",
            "backend/commands/notebookAndPage/getPageType.py",
            "backend/commands/notebookAndPage/pageInfo.py",
            "backend/commands/notebookAndPage/updatePage.py",
            "backend/commands/notebookAndPage/copyPage.py",
            "backend/commands/notebookAndPage/createPage.py",
            "backend/commands/notebookAndPage/deletePage.py",
            "backend/commands/notebookAndPage/movePage.py",
            "backend/commands/notebookAndPage/renamePage.py",

            "backend/commands/notebookAndPage/addTag.py",
            "backend/commands/notebookAndPage/createTag.py",
            "backend/commands/notebookAndPage/deleteTag.py",
            "backend/commands/notebookAndPage/getTagList.py",
            "backend/commands/notebookAndPage/queryTag.py",
            "backend/commands/notebookAndPage/removeTag.py",

            "backend/commands/notebookAndPage/fileAdd.py",
            "backend/commands/notebookAndPage/fileData.py",
            "backend/commands/notebookAndPage/fileDelete.py",
            "backend/commands/notebookAndPage/fileInfo.py"
        ],
        "InterruptModules":[
            "backend/interrupts/newInfo.py",
            "backend/interrupts/updatePage.py",
            "backend/interrupts/updateTag.py"
        ],
        "TaskModules":[
            "backend/tasks/pageCleaner.py",
            "backend/tasks/showPingMessage.py"
        ]
    },
    "extensionDependencies":[

    ]
}

変更後
{
    "name": "Core",
    "UUID": "589fe65d-639c-42a3-b395-fca2143afd75",
    "description": "Manage notebook and pages. Provide basic notebook interface.",
    "frontend":{
        "modules": []
    },
    "DataServer":{
        "CommandModules":[
            "backend/commands/info.py",

            "backend/commands/notebookAndPage/createNotebook.py",
            "backend/commands/notebookAndPage/deleteNotebook.py",
            "backend/commands/notebookAndPage/getPageType.py",
            "backend/commands/notebookAndPage/pageInfo.py",
            "backend/commands/notebookAndPage/updatePage.py",
            "backend/commands/notebookAndPage/copyPage.py",
            "backend/commands/notebookAndPage/createPage.py",
            "backend/commands/notebookAndPage/deletePage.py"
        ],
        "InterruptModules":[
            "backend/interrupts/newInfo.py",
            "backend/interrupts/updatePage.py",
            "backend/interrupts/updateTag.py"
        ],
        "TaskModules":[
            "backend/tasks/pageCleaner.py",
            "backend/tasks/showPingMessage.py"
        ]
    },
    "extensionDependencies":[

    ]
}

DataServer における拡張機能読み込みの実装の進捗

 とりあえず1つも読み込む拡張機能がないときに、runtime.pyを生成させるところまでは動くようになってきた。

コンソールのログ

python main.py --loadExtension
# Current settings -------------------------
# {'backendBaseFolderPath': '/home/UserName/work/OneNoteAlternative/secondPrototype/backend'}
# <class 'dict'>
# source /home/UserName/work/OneNoteAlternative/secondPrototype/backend/dataServerVenv/bin/activate
# 
# Loading extensions is begun ---------------
# Loading extensions is begun ---------------
#         /home/UserName/work/OneNoteAlternative/secondPrototype/backend
#         /home/UserName/work/OneNoteAlternative/secondPrototype/backend/extensions/
#         /home/UserName/work/OneNoteAlternative/secondPrototype/backend/extensions/runtime/
#         /home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/
#         /home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/controller/runtime.py
# 
# 0 extensions are found.

生成された空の runtime.py

# Command

commandExtensionMoludes = {

}


# Interrupt

interruptExtensionMoludes = {

}


# Task

taskExtensionMoludes = {

}

DataServer 起動において仮想環境を使うように実装

 mainSys が用意された仮想環境内で起動するように実装した。これにより、既存のホストマシンの Python 環境をなるべく汚さないようにしている。

DataServer の設定の実装を二段階に分けた

 DataServer 起動時において、2つの段階を用意した。基本的には、firewalld を使った経験を背景に実装した。

 firewalld では、メモリ上に配置されていて、動的に変更される一時的な設定と、ファイルシステム上に配置されていて永続化した設定が保存される2つの設定が存在し、それを真似ている。

 しかし完全に同じというわけではなく、動的な設定もファイルシステム上に書き出される。完全に動的なのではなく、DataServer の mainSys を起動する準備段階において、動的に設定が決定されるというようなものである。 

settings.json

 永続化した設定が保存される。動的に解決され、バックエンドのパスなど明記されない項目もある。

mainSys/runtime.json

 動的に生成された設定が保存される。現状では主に、バックエンドとノートブックのデータのルートとなるパスがどこかが解決された設定が保存されている。mainSys サブシステム起動時に読み込まれ、それ以降の動作に設定が伝搬するようになっていある。ユーザはこの設定を勝手にいじることは禁止される。

何も拡張機能がない状態でとりあえず動くようにした

 とりあえず、卒論のフロントエンドの試作物と今回試作しているものの一部である DataServer が実際に接続できて、動作することが確認できた。

研究に関係ありそうなブログ記事

参考にしたサイトとか