Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rust APIが公開するエラーの種類をErrorKindとして表現する #589

Merged
merged 7 commits into from
Sep 3, 2023

Conversation

qryxip
Copy link
Member

@qryxip qryxip commented Aug 27, 2023

内容

voicevox_core::ErrorKindを追加し、voicevox_core::Errorはopaqueにします。それに伴い、voicevox_core::Error以外のエラー型の可視性をすべてpub(crate)にします。

Python/Java/Rust(今後) APIのためにRust APIを整理することが目的です。

関連 Issue

#580 の続きです。

ref #545

その他

Copy link
Member Author

@qryxip qryxip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

補足:

@@ -26,6 +72,7 @@ pub enum Error {
#[error("無効なspeaker_idです: {style_id:?}")]
InvalidStyleId { style_id: StyleId },

#[allow(dead_code)] // FIXME
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UnloadedModelと統合される形になると思ってます。

/// OpenJTalkのユーザー辞書の設定に失敗した。
UseUserDict,
/// ユーザー辞書の単語のバリデーションに失敗した。
InvalidWord,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここのdocは現状のResultCodeからそのまま持って来ました。

crates/voicevox_core/src/user_dict/word.rs Show resolved Hide resolved
Comment on lines -1220 to -1246

#[cfg(test)]
mod tests {
use super::*;
use anyhow::anyhow;
use pretty_assertions::assert_eq;
use voicevox_core::Error;
use voicevox_core::Result;

#[rstest]
#[case(Ok(()), VoicevoxResultCode::VOICEVOX_RESULT_OK)]
#[case(
Err(Error::NotLoadedOpenjtalkDict),
VoicevoxResultCode::VOICEVOX_RESULT_NOT_LOADED_OPENJTALK_DICT_ERROR
)]
#[case(
Err(Error::GetSupportedDevices(anyhow!("some get supported devices error"))),
VoicevoxResultCode::VOICEVOX_RESULT_GET_SUPPORTED_DEVICES_ERROR
)]
fn into_result_code_with_error_works(
#[case] result: Result<()>,
#[case] expected: VoicevoxResultCode,
) {
let actual = into_result_code_with_error(result.map_err(Into::into));
assert_eq!(expected, actual);
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

今はe2eがあるし、ここが果たす役割もそう多くないと思ったので削除。

Comment on lines 7 to 9
pub fn validate_pronunciation(pronunciation: &str) -> std::result::Result<(), impl Display> {
crate::user_dict::validate_pronunciation(pronunciation)
}
Copy link
Member Author

@qryxip qryxip Aug 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InvalidWordErrorという型を隠蔽したままPython APIに輸出するため。

Copy link
Member

@Hiroshiba Hiroshiba Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここ実装が正直ちょっといびつだなと感じました!

UserDictWordのpronunciationのpydantic.validationをなくすと、pronunciationは誰からもvalidationされない感じなんでしたっけ。。だったらとりあえずここに書くのは仕方なそう。
もしUserDictWordを使用する関数(add_word)内でvalidationエラーになる場合は・・・どうすべきか難しいですね・・・。

うーーーーん、validate_user_dict_word関数を作成するとか・・・?
まあでもどちらにせよこのプルリクエストで解決することではなさそうなので、とりあえずFIXME書くとかでもいいかも。。

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#595 を作りました。

関数のシグネチャと、__internalという名の#[doc(hidden)]なモジュールに包まれていることから、意図にコメントは要らないかなと思うので、FIXMEが無くても上記のissueがあるだけでよいかなと思いました。

Copy link
Member

@Hiroshiba Hiroshiba Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほどです。
確かにソースコードがやっていることの意図はわかると思います。
ただ、この部分は今仕方なくこうなっていて、どちらかというと改修したい対象だということが実装からはわからなそう・・・?

そのことをコメントか何かに書いとくのどうでしょう。
例えば、この辺りの実装を発展させたプルリクエストを抑止できるかなぁと。

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXMEを入れました。
e8045e4 (#589)

@qryxip qryxip mentioned this pull request Aug 27, 2023
69 tasks
@@ -49,7 +49,7 @@ fn string_feature_by_regex(re: &Regex, label: &str) -> Result<String> {
}

impl Phoneme {
pub fn from_label(label: impl Into<String>) -> Result<Self> {
pub(crate) fn from_label(label: impl Into<String>) -> Result<Self> {
Copy link
Member Author

@qryxip qryxip Aug 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

各エラー型の可視性の降格により、シグネチャにそれらのエラー型が表われる関数がコンパイルエラーになるので同様に可視性を調整。

これによりコード中に特に理由無くpubpub(crate)が混在することになりますが、Rust API内のアイテムの可視性については元々深く考えられていないということで今のところはよいかなと思いました。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

混じってしまうのはまあありなのかなと思いました。
ただ混じってしまうぐらいなんだったら、今は全部統一的にpubにしておいて、pub(crate)にする機会を別途作成してそこで一気に変更とかもありかもとか思いました。

まあでもせっかく書いちゃったんだし、こちらのプルリクエストの形で一旦マージするのもありかもです。
あまり強い意見ではないです。

Copy link
Member Author

@qryxip qryxip Aug 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#594 を作りました。
(初心者歓迎タスクにしました)

Copy link
Member

@Hiroshiba Hiroshiba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

全部読みました!

タイトル周りの変更はLGTMなのですが、可視性の変更周りでいくつか気になったのでコメントしてみました。
APIの実装的にはおそらく戻って全部一気に変更した方がいいのですが、まあ実装しちゃったし戻すのそこまでモチベーションないということであれば、とりあえずマージでもそんなに問題じゃないかなと思います。

@Hiroshiba
Copy link
Member

Hiroshiba commented Aug 28, 2023

あ、もう1点質問です!
そもそも何の目的のためにこの整理を行う感じでしょうか? 👀

Comment on lines +11 to +12
#[error(transparent)]
pub struct Error(#[from] ErrorRepr);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

多分できることがError==ErrorReprだと思うのですが、であれば最初から内部で使う構造体もErrorで良いのではとちょっと思いました。
メリットがあれば知りたいです。
あるいは一般的にクレート内のエラー構造体と外に出すエラー構造体はレイヤーが異なるため型を分けるべきである、みたいな思想があるのであれば一旦従うのもありかなと思いました。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらのコメントで納得したのでResolveです!

@qryxip
Copy link
Member Author

qryxip commented Aug 29, 2023

#589 (comment)への返答でもあるのですが、Rustのpublic APIとしての情報に制限をかけたかったからです。public APIとしてはこのリポジトリの場合、

  1. std::error::Errorとしての機能
  2. エラーの種別

のみを露出するのが適切で、それ以外を隠蔽するようにしたらこの形になりました。

またエラー型に限らずenumの形をnewtypeパターンで隠蔽するのは、少なくともRustにおいては一般的です。今回はthiserrorのドキュメントに載っていた以下の形に従いました。クラス間の「継承」があったり、そもそも型付けが弱い言語だとそもそも選択肢に挙がらないパターンだとは思います。

// PublicError is public, but opaque and easy to keep compatible.
#[derive(Error, Debug)]
#[error(transparent)]
pub struct PublicError(#[from] ErrorRepr);

impl PublicError {
    // Accessors for anything we do want to expose publicly.
}

// Private and free to change across minor version of the crate.
#[derive(Error, Debug)]
enum ErrorRepr {
    ...
}

thiserror - Rust

@@ -54,6 +101,49 @@ pub enum Error {
InvalidWord(InvalidWordError),
}

/// エラーの種類。
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum ErrorKind {
Copy link
Member Author

@qryxip qryxip Aug 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ErrorKindの定義および変換をしてくれるライブラリがあった。
kinded

作者はnutypewhatlangを作った人。強制的にDisplay/FromStrが付く点には異議を唱えたいところではあるが、それ以外は筋がよいと感じるし、実装のコードも簡潔。

が、initial commitが28日前、最終更新日が21日前で、総ダウンロード数658…

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

もうちょっと待ってみて、ライブラリ側やこちら側も安定して来てそうだったら導入を検討しても良さそうなのかなと思いました!

@Hiroshiba
Copy link
Member

あとこの2点かなと!
#589 (comment)
#589 (comment)

@qryxip
Copy link
Member Author

qryxip commented Sep 3, 2023

Copy link
Member

@Hiroshiba Hiroshiba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!!!

メンテナンス性向上のためのコメントの提案と、素人考えのコメントを書いてみました。

crates/voicevox_core/src/__internal.rs Show resolved Hide resolved
crates/voicevox_core/src/__internal.rs Show resolved Hide resolved
@Hiroshiba
Copy link
Member

問題ないと思うのでマージします!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants