Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .index.yml

This file was deleted.

12 changes: 12 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,17 @@
"**/小説データ/**": true,
"**/.narou_perf_test/**": true,
"**/小説データ_perf_test/**": true
},
"rubyLsp.indexing": {
"excludedPatterns": [
"frontend/**/*",
"node_modules/**/*",
"vendor/**/*",
"tmp/**/*",
"log/**/*",
".git/**/*",
"**/spec/**/*",
"**/test/**/*"
]
}
}
2 changes: 1 addition & 1 deletion docs/html_parser_analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ json_data_source:
type: "application/json"
paths:
work_id: "query.workId"
toc: "props.pageProps.__APOLLO_STATE__.Work:{workId}.tableOfContents"
toc: "props.pageProps.__APOLLO_STATE__.Work:{workId}.tableOfContentsV2"
title: "props.pageProps.__APOLLO_STATE__.Work:{workId}.title"
author: "props.pageProps.__APOLLO_STATE__.Work:{workId}.author.__ref"

Expand Down
22 changes: 13 additions & 9 deletions docs/process_management.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ narou-modは堅牢なプロセス管理機能を提供し、サーバーの起

- 既存のnarou-modプロセスが実行中かどうか
- 必要なポート(デフォルト: 5678, 5679, 4321)が使用可能かどうか
- プロセス情報ファイル(`tmp/pids/*.pid`)の整合性
- プロセス情報ファイル(`<システム一時ディレクトリ>/narou-mod/<hash>/pids/*.pid`)の整合性

### 2. ポート競合検出

Expand Down Expand Up @@ -49,10 +49,12 @@ bundle exec ruby narou.rb web --force

## プロセス情報ファイル

プロセス情報は`tmp/pids/`ディレクトリに保存されます:
プロセス情報はシステムの一時ディレクトリ配下に保存されます(プロジェクトごとにハッシュで分離):

```bash
tmp/pids/
# Linux: /tmp/narou-mod/<hash>/pids/
# macOS: /var/folders/.../T/narou-mod/<hash>/pids/
pids/
├── narou-backend.pid # バックエンドプロセス情報
├── narou-backend.port # 使用ポート
├── narou-frontend.pid # フロントエンドプロセス情報
Expand Down Expand Up @@ -98,13 +100,13 @@ bundle exec ruby narou.rb web --force
### プロセスのクリーンアップ

```bash
./bin/cleanup_processes.sh
./scripts/process_control.sh
```

または

```bash
./bin/cleanup_processes.sh -y # 自動承認
./scripts/process_control.sh --kill --force # 確認なしで全プロセス終了
```

## トラブルシューティング
Expand All @@ -121,7 +123,7 @@ bundle exec ruby narou.rb web --force
**対処法:**

1. 表示されたプロセスを手動で停止: `kill 12345`
2. クリーンアップスクリプトを実行: `./bin/cleanup_processes.sh`
2. クリーンアップスクリプトを実行: `./scripts/process_control.sh`
3. 別のポートを指定: `narou web -p 8000`
4. 強制起動: `narou web --force`

Expand All @@ -131,14 +133,16 @@ Windows側とWSL側や、ホスト側とDocker側で別々にプロセスが起

1. **Windows/ホストOS側を確認**: タスクマネージャーまたは`tasklist | findstr ruby`や、ホストOSのプロセス管理ツールで確認
2. **WSL/Docker側を確認**: `ps aux | grep ruby`
3. **両方をクリーンアップ**: 各環境で`cleanup_processes.sh`を実行
3. **両方をクリーンアップ**: 各環境で`scripts/process_control.sh`を実行

### PIDファイルが残っている

プロセスが異常終了した場合、PIDファイルが残ることがあります:

```bash
rm -f tmp/pids/*.pid tmp/pids/*.port
# 現在のプロジェクトの一時ファイルのみ削除(ruby で tmp_dir を確認)
ruby -e 'require "tmpdir"; require "digest"; hash = Digest::SHA256.hexdigest(Dir.pwd)[0,8]; puts File.join(Dir.tmpdir, "narou-mod", hash)'
# 表示されたパスを削除
```

または起動時に自動的にクリーンアップされます。
Expand Down Expand Up @@ -174,4 +178,4 @@ rm -f tmp/pids/*.pid tmp/pids/*.port

- [process_manager.rb](../lib/narou/process_manager.rb) - 実装
- [process_manager_spec.rb](../spec/narou/process_manager_spec.rb) - テスト
- [cleanup_processes.sh](../bin/cleanup_processes.sh) - クリーンアップスクリプト
- [process_control.sh](../scripts/process_control.sh) - クリーンアップスクリプト
4 changes: 2 additions & 2 deletions lib/cli/command/web.rb
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ def stop_frontend_process
end

def stop_frontend
frontend_pid_file = File.join(Narou.root_dir, "tmp", "pids", "narou-frontend.pid")
frontend_pid_file = File.join(Narou.tmp_dir, "pids", "narou-frontend.pid")

return unless File.exist?(frontend_pid_file)
pid = File.read(frontend_pid_file).to_i
Expand All @@ -306,7 +306,7 @@ def should_start_frontend?

def start_frontend
frontend_dir = File.join(Narou.root_dir, "frontend")
frontend_log = File.join(Narou.root_dir, "tmp", "logs", "narou-frontend.log")
frontend_log = File.join(Narou.tmp_dir, "logs", "narou-frontend.log")

Command::OutputHelper.info("フロントエンドサーバーを起動しています...")

Expand Down
6 changes: 3 additions & 3 deletions lib/cli/command/web_legacy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def boot

if @daemon_mode
$stdout.puts "WEBサーバーをバックグラウンドで起動しています..."
$stdout.puts "ログ: tmp/logs/narou-web.log"
$stdout.puts "ログ: #{File.join(Narou.tmp_dir, "logs", "narou-web.log")}"
end

max_retries = 5
Expand Down Expand Up @@ -362,7 +362,7 @@ def daemonize
write_pid_file

# ログファイルにリダイレクト
log_file = File.join(Narou.root_dir, "tmp", "logs", "narou-web.log")
log_file = File.join(Narou.tmp_dir, "logs", "narou-web.log")
log_dir = File.dirname(log_file)
FileUtils.mkdir_p(log_dir) unless File.exist?(log_dir)
$stdout.reopen(log_file, "a")
Expand All @@ -380,7 +380,7 @@ def daemonize
end

def pid_file_path
File.join(Narou.root_dir, "tmp", "pids", "narou-web.pid")
File.join(Narou.tmp_dir, "pids", "narou-web.pid")
end

def write_pid_file
Expand Down
16 changes: 16 additions & 0 deletions lib/core/narou.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
# Copyright 2013 whiteleaf. All rights reserved.
#

require "digest"
require "fileutils"
require "memoist"
require "pathname"
require "tmpdir"
require "active_support/core_ext/object/blank"
require "lib/utilities/helper"
require "lib/core/inventory"
Expand Down Expand Up @@ -48,6 +50,20 @@ def last_commit_year
2025
end

# PIDファイルやログなど一時ファイル用ディレクトリ
# Narou.root_dir/tmp/ ではなくシステムの一時ディレクトリを使用することで
# ホームディレクトリに ~/tmp が作成される問題を回避する
# root_dir ごとにハッシュでネームスペースを分離し、複数インスタンスの干渉を防ぐ
def tmp_dir
root = root_dir
if root
hash = Digest::SHA256.hexdigest(root.to_s)[0, 8]
File.join(Dir.tmpdir, "narou-mod", hash)
else
File.join(Dir.tmpdir, "narou-mod", "default")
end
end

def root_dir
root = nil
path = Dir.pwd
Expand Down
9 changes: 4 additions & 5 deletions lib/narou/process_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ class PortConflictError < StandardError; end

attr_reader :pid_file_path, :port_file_path

def initialize(service_name, root_dir: Narou.root_dir)
def initialize(service_name)
@service_name = service_name
@root_dir = root_dir
@pid_dir = File.join(@root_dir, "tmp", "pids")
@pid_dir = File.join(Narou.tmp_dir, "pids")
@pid_file_path = File.join(@pid_dir, "#{@service_name}.pid")
@port_file_path = File.join(@pid_dir, "#{@service_name}.port")

Expand Down Expand Up @@ -138,7 +137,7 @@ def cleanup_stale_process!
停止するには以下のコマンドを実行してください:
kill #{pid}
または
./bin/cleanup_processes.sh -y
./scripts/process_control.sh --kill --force
MSG
end

Expand Down Expand Up @@ -166,7 +165,7 @@ def check_port_conflict!(port, host = "127.0.0.1")
以下のいずれかの対処を行ってください:
1. ポートを使用しているプロセスを停止する
2. 別のポートを指定する(--port オプション)
3. ./bin/cleanup_processes.sh を実行して関連プロセスをクリーンアップする
3. ./scripts/process_control.sh を実行して関連プロセスをクリーンアップする
MSG

raise PortConflictError, error_msg
Expand Down
2 changes: 1 addition & 1 deletion lib/web/api/v1/system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def self.register(app)
backend_pid = ::Process.pid # 現在のプロセスのPID

# フロントエンドのステータスは引き続きPIDファイルで判定
frontend_pid_file = File.join(Narou.root_dir, "tmp", "pids", "narou-frontend.pid")
frontend_pid_file = File.join(Narou.tmp_dir, "pids", "narou-frontend.pid")
frontend_running = false
frontend_pid = nil

Expand Down
2 changes: 1 addition & 1 deletion preset/parsers/kakuyomu.jp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ json_data_source:
type: "application/json"
paths:
work_id: "query.workId"
toc: "props.pageProps.__APOLLO_STATE__.Work:{workId}.tableOfContents"
toc: "props.pageProps.__APOLLO_STATE__.Work:{workId}.tableOfContentsV2"
title: "props.pageProps.__APOLLO_STATE__.Work:{workId}.title"
author: "props.pageProps.__APOLLO_STATE__.Work:{workId}.author.__ref"
story: "props.pageProps.__APOLLO_STATE__.Work:{workId}.introduction"
Expand Down
4 changes: 2 additions & 2 deletions spec/cli/command/web_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

before do
# PIDファイルのクリーンアップ
pid_dir = File.join(Narou.root_dir, "tmp", "pids")
pid_dir = File.join(Narou.tmp_dir, "pids")
FileUtils.rm_f(Dir.glob(File.join(pid_dir, "*.pid"))) if File.exist?(pid_dir)

# OutputHelperのモック(標準出力への出力を抑制)
Expand Down Expand Up @@ -142,7 +142,7 @@

describe "#start_frontend" do
let(:frontend_dir) { File.join(Narou.root_dir, "frontend") }
let(:frontend_log) { File.join(Narou.root_dir, "tmp", "logs", "narou-frontend.log") }
let(:frontend_log) { File.join(Narou.tmp_dir, "logs", "narou-frontend.log") }

before do
# frontend ディレクトリが存在することを前提とする
Expand Down
15 changes: 9 additions & 6 deletions spec/narou/process_manager_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,28 @@
require "lib/narou/process_manager"

describe Narou::ProcessManager do
let(:test_dir) { Dir.mktmpdir }
let(:test_tmp_dir) { Dir.mktmpdir }
let(:service_name) { "test-service" }
let(:manager) { described_class.new(service_name, root_dir: test_dir) }
let(:manager) do
allow(Narou).to receive(:tmp_dir).and_return(test_tmp_dir)
described_class.new(service_name)
end

after do
FileUtils.rm_rf(test_dir)
FileUtils.rm_rf(test_tmp_dir)
end

describe "#initialize" do
it "sets correct file paths" do
expect(manager.pid_file_path).to eq(File.join(test_dir, "tmp", "pids", "#{service_name}.pid"))
expect(manager.port_file_path).to eq(File.join(test_dir, "tmp", "pids", "#{service_name}.port"))
expect(manager.pid_file_path).to eq(File.join(test_tmp_dir, "pids", "#{service_name}.pid"))
expect(manager.port_file_path).to eq(File.join(test_tmp_dir, "pids", "#{service_name}.port"))
end
end

describe "#register_process" do
it "creates PID directory and file" do
manager.register_process
expect(File.directory?(File.join(test_dir, "tmp", "pids"))).to be true
expect(File.directory?(File.join(test_tmp_dir, "pids"))).to be true
expect(File.exist?(manager.pid_file_path)).to be true
end

Expand Down
4 changes: 2 additions & 2 deletions webnovel/kakuyomu.jp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ confirm_over18: no
append_title_to_folder_name: yes
title_strip_pattern: null
sitename: *name
version: 2.1
version: 2.2

# ------------------------------------------------------------
# 前処理設定
Expand All @@ -28,7 +28,7 @@ code: &code
# work: この作品のデータ
work = data["Work:#{json["query"]["workId"]}"]
# まずTOCを処理する
toc = work["tableOfContents"]
toc = work["tableOfContentsV2"]
# workのTOCはTableOfContentsChapterの参照の配列となっているので、それを解決する
toc.map! {|v| data[v["__ref"]]}
# TableOfContentsChapterにはChapterと各話の配列があるのでそれを取り出し
Expand Down
Loading