Skip to content

Latest commit

 

History

History
129 lines (115 loc) · 8.67 KB

File metadata and controls

129 lines (115 loc) · 8.67 KB

クライアント/バックエンド間のAPI設計

ユーザー登録

このタイミングは初回起動時ではなくサイトを購読した時に行う

  • その時初めてユーザーがサービスを使い始めたと認識する
    • バックエンド側でランダム生成したユーザーIDをクライアントに返信する
  • レコメンドするExploreCategoryは初回では国ごとに設定されたものを表示する

設定を同期

クライアントの設定をクラウドに送信してクラウドの設定を上書きする だが、他のプラットフォーム上で設定が変更されていたらどうするべきか

  • お気に入り・サイト購読解除・テキストサイズなど設定を変更するたびにクラウドに同期する
  • そして、設定日時が新しい方を優先して上書きか読み込んで返すか

コード同期

異なるプラットフォームでも同じサービス体験が出来るようにする コード同期はQRコードとピンコードの二種類 コードを元に同期するアカウントを割り出して設定を読み込んで返す

アクテビティを報告

記事を読んだりした時にクラウドに報告する ランキングを作るために必要

  • だが、ポートフォリオにおいてランキングは擬似的に作る

検索

記事タイトルやサイト名でデータベースを検索する

Explore Categoryの取得

ランキングと同様に国ごとに合わせたカテゴリーをデータベースから読み取って返信する

ランキング取得

データベースから国ごとのランキングを取得する

  • 今はまだランキングは擬似的に作る

クラウドフィード取得

サイトを指定してクラウドからフィードを取得する データベースにない場合は新規に取得する事になる

  • この処理をクライアント側で行うとクライアント側での実装が複雑になる
  • この処理は処理時間が長くなるので、リソースは多めに割り当てる
    • サイトのURLからHTMLをパースしてフィードURLを取得する
    • フィードURLからフィードを取得する
      • もし画像リンクが無かったら記事にアクセスしてHTMLをダウンロードして画像リンクを取得する
        • この処理は時間が掛かるのでクライアントにやらせるか検討
    • フィードをデータベースに格納してクライアントにフィードを返信する
  • 以後、フィードの更新はバックエンドのバッチ処理で行う

開発言語

バックエンドのLambda関数は全てGoで実装する

  • 一つのLambda関数に複数の処理を書くのは可読性保守性が下がり、ベストプラクティスに反するのでいくつかのLambda関数に分ける方針
  • 機能毎にLambda関数を分けないのは、Lambda関数の数が多くなりすぎて管理が大変になるから
  • バックエンドにRustではなくGoを使って実装する理由は、Goは多くの企業がバックエンドで採用している言語であり、スキルマッチなどで今後のキャリアに繋がると判断した
    • Rustは効率性などでGoよりも優れているが、Goを採用している企業が多いからポートフォリオとしてはRustを採用する理由はないと判断した
  • APIのRead/Write系はDBを読み書きするだけだからGraphQLでも代替可能だが、それのためだけにGraphQLを使うのは工数・日程などで難しいので今はOpenAPIに集中しておく

DBを読み出すだけの処理

  • Explore Categoryの取得(ユーザーID)
  • ランキング取得 (ユーザーID)
    • 次のバージョンアップで実装
  • トレンド取得 (ユーザーID)
    • まだトレンドは実装していない

ユーザー処理

  • (API応答)初回起動時のユーザーID生成 (ユーザー識別情報)
  • (ConfigSyncResponse)設定を同期(ユーザーID,ユーザー識別情報)
    • 起動時にユーザーIDを元に最新の設定を取得してクライアントに返信する
    • APIリクエスト制限・ユーザー情報を取得してクライアント側で色々と処理をする
    • ユーザー設定はUIや購読サイトなどの設定情報も入っているのでここで実装する
    • ユーザー設定テーブル自体はシンプルにする
    • ユーザー設定を取得する時にユーザーIDをキーにして各テーブルから取得する
  • (API応答)ユーザー登録(ユーザー設定,ユーザー識別情報)
    • クライアント側
      • ユーザーIDを受け取ったら色々処理をしてユーザー設定をクラウドに送信
    • クラウド側
      • Jsonからデータに変換してDBに登録する
  • (API応答)閲覧アクテビティを報告(ユーザー閲覧アクティビティ)
  • (API応答)設定を更新(ユーザー設定)
    • UI設定を変更したらクラウドに送信してクラウドの設定を上書きする
  • (検索履歴)検索履歴を編集(ユーザーID,テキスト,bool 追加・削除)
    • 検索履歴を編集・削除する
  • (API応答)サイトをお気に入り・お気に入り解除(ユーザーID,Webサイト,bool 追加・削除)
  • (API応答)記事をお気に入り・お気に入り解除(ユーザーID,記事,bool 追加・削除)
  • (APIリクエスト制限) APIリクエスト制限取得(ユーザーID,ユーザー識別情報)
    • APIリクエスト制限を取得する
    • クライアント側で起動時などでAPIリクエスト制限を取得する

サイト系処理

  • (検索結果)検索(API検索リクエスト)
    • サイト検索で未登録サイトなら、登録処理をして結果を返す
    • キーワード検索・登録済みサイトならDBを読み出すだけ
    • URLを直接検索欄に入力するパターンもあるから、URLからサイトを登録する処理も実装する
  • (API応答)サイトを購読・購読解除
    • サイトが登録されていなかったら登録処理をしてから購読を登録する
    • Feedの時間はRFC3339形式で返す
  • (クラウドフィード取得応答)クラウドフィード取得
    • クライアントからかLambdaEvent経由で起動
    • クライアント側が記事を保存するから欲しいのが最古なのか最新なのかを指定する
      • 初期・Webフロントエンドでは最新から100件を上限に取得する
    • サイトのURLからDBを検索してフィードの最終更新チェック日時が一定期間経過していたらフィードを取得更新する
    • 更新したらフィードを取得する

この三つに分けて実装する

API定義言語

  • 当初は未挑戦の技術であるGraphQLを使う予定だったが。。。
  • 調べていくと数々の困難があり結局OpenAPIに切り替える記事が結構出てきたのでOpenAPIを使うことにする
  • OpenAPIではやりとりする型を全て定義はしない
    • コードが膨大になり仕様変更時に工数が大変になるからArgumentをJsonとしてやり取りすることにする

APIリクエスト制限

  • リソースは有限なのと、有料会員との差別化をする為にAPIリクエスト制限を設ける
    • この処理はクライアント側で実装する
    • 制限に達したらキューに貯めておいて、制限が解除されたらキューから取り出して送信処理する
  • ただし、頻度が少ないと予想されるユーザー登録とコード同期と設定更新と検索履歴とお気に入り・購読登録は制限しない
  • だが、ポートフォリオの段階では工数の問題で実装しないまま「最小限のプロダクト(MVP)」としてリリースする
    • 改修は余裕ができた後で行う