紆余曲折合ってはてなブックマークの運用を見直す必要が出てきました。人の興味というのは尽きないもので知りたいことが次々出てきます。にも拘わらず人の時間は有限でそれにあがなうための手段を考えたわけです。
というわけで、下記の方針でブクマすることにしました。設置方法の詳細はGitHubレポジトリを参照ください。そして、方針は下記の通りになります。
方針
まずブクマの管理ですが、下記5つのYAMLファイルで構成しています、構造はマップとリストのみ。ブクマしたいと思う記事を読みすすめる中で気になるキーワードが出てきたら都度 feed.yaml
を更新します。また、記事にノイズが多いようだったら傾向を分析して除外ファイル feed_excluded_link.yaml
feed_excluded_title.yaml
を更新します。
item | description |
---|---|
feed.yaml |
フィードグループ名に対するリンク、タグのマップ |
feed_excluded_link.yaml |
除外すべきフィードリンクのリスト |
feed_excluded_title.yaml |
除外すべきフィードタイトルのリスト |
feed_corrected_link.yaml |
フィードリンクに対するトリミングすべきパラメータのマップ |
feed_redirected_link.yaml |
フィードリンクに対するリダイレクト先リンクのマップ |
# feed.yaml
nabinno/sports/feed_group_name:
tags:
- ski
links:
- http://rss.example.com/ski_feed.rss
- http://rss.example.com/snowboard_feed.rss
- http://ski-status.example.com/rss
# feed_excluded_link.yaml
- anti-ski.example.com
- awesome-snowboard.example.com
# feed_excluded_title.yaml
- queer
- two-planker
- beaver-tail
# feed_corrected_link.yaml
amazon.com:
- ref
- ie
# feed_redirected_link.yaml
ski-status.example.com:
- Floki.find(fst, ".post__body a")
Elixirで非同期処理を行っているのですが、大きく分けて監視機構のSupervisorと非同期処理のTask.async_streamを使っています。
まず、Supervisor。Elixirには監視機構Supervisorがあり、それが各ワーカーを子プロセスとして管理しています。ここではフィード読込とブクマは別々のワーカーで処理しますが、キャッシュが暖気処理を別ワーカーで行っているため再起動戦略は「失敗したイベントの中にあるすべての子プロセスを再起動」( one_for_all
)にしてあります。再起動戦略の詳細は「OTPスーパバイザ · Elixir School」を参照下さい。
下記のように Supervisor.start_link
を Keshikimi2.Application.start
に適用すると、アプリケーション開始( mix run
)した時点で監視機構が起動されます。
Supervisor.start_link(
[
:hackney_pool.child_spec(:hatena_bookmark_pool, timeout: 15_000, max_connections: 100),
# @todo 当該ワーカーで暖気処理を行っていないので `one_for_one` にした場合、再起動時にほかに影響する
supervisor(Cachex, [:feed, []]),
supervisor(Keshikimi2Feed.Registry, [prefix]),
# フィード読込処理 (PubSub)
supervisor(Keshikimi2Feed.Subscriber, [prefix]),
worker(Keshikimi2Feed.Worker, [prefix]),
worker(Keshikimi2Feed.Publisher, [[prefix: prefix, poll_interval: 3_000]]),
# ブクマ処理
worker(Keshikimi2.HatenaBookmark.AddEntry, [
[prefix: prefix, poll_interval: 3_000]
])
],
strategy: :one_for_all,
name: name(prefix)
)
次に、Task.async_stream。配列を引き回すリクエスト処理は Task.async_stream
がうってつけです。下記ではキャッシュからブクマ対象になるフィードリンクを取り出し、除外処理、校正処理を加えて、ブクマのリクエストを出すという流れを組んでいます。Elixirでは、流れをひとまとめにして視覚的にわかりやすく非同期処理してくことができます。
Cachex.keys!(:feed)
|> Enum.reject(fn key ->
key in [
"excluded_links",
"excluded_titles",
"corrected_links",
"redirected_links",
"feed_group",
"archived_links"
]
end)
|> Task.async_stream(
fn item_link ->
with {:ok, [item_title, feed_tags]} <- Cachex.get(:feed, item_link),
:ok <- validate_all(item_link, item_title),
corrected_link <- correct_all(item_link),
{:ok, payload} <-
FormData.create(
%{
url: corrected_link,
comment: feed_tags |> Enum.map_join(fn tag -> "[#{tag}]" end),
rks: System.get_env("HATENA_BOOKMARK_RKS"),
private: 0,
keep_original_url: 1,
with_status_op: 1,
from: "inplace",
post_twitter: 0,
post_evernote: 0
},
:url_encoded,
get: false
) do
do_add_entries_to_hb(payload)
Logger.info("add entry: #{item_link}")
end
archive_link(item_link)
end,
timeout: 15_000
)
|> Stream.run()
Elixirの非同期処理を使うことではてなブックマークの運用がとても快適になりました。はてなブックマークとの今後の付き合い方は下記のように考えています。
ブクマの確認については、例えば、CIでデプロイしている間に最近のGitHubの動向を確認したい場合は「nabinno/github」をみる、という感じの運用です。
融通が利かない点で途中運用が難しくなる気もしますが、しばらく回してみます。
テクノロジーの進化は、絶え間ない変化の中で私たちの日常を塗り替えてきました。時には経済的な危機が、新たな可能性を切り拓く契機となることもあります。そこで、過去のリセッション期に生まれたテクノロジーの足
ATKerneyの課題解決パターン は、課題の本質を見極め、効果的な戦略的構造化を通じて解決策を導き出す手法にフォーカスしています。この冒険の旅は、解決者と協力者たちが心を一つにし、課題に立ち向かう様
私はいわゆる就職氷河期世代です。周囲から時折漏れ聞こえる不平のような言葉がありますが、それを単なる不平として片付けるのはもったいない気がします。できれば、その中に新しい視点を見つけ、次のチャンスへ繋げ