Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ゆっくり動くと速く動ける / If you move slowly, you can move more fast

ゆっくり動くと速く動ける / If you move slowly, you can move more fast

Ruby on Railsの抽象インタフェース(ActiveRecord/ActiveJob)を使うことで、アプリケーションのアーキテクチャ決定を遅らせる事ができる。アーキテクチャの決定を遅らせ、アプリケーションの構成をなるべく長い期間シンプルに保つと、開発速度を上げることができます。
Rails Developers Meetup 2018 Day 4 Nouvelle Vague https://techplay.jp/event/702297 にて発表

shigeru. nakajima

December 08, 2018
Tweet

More Decks by shigeru. nakajima

Other Decks in Technology

Transcript

  1. Ώͬ͘Γಈ͘ͱ଎͘ಈ͚Δ
    Rails Developers Meetup 2018 Day 4 Nouvelle Vague 2018/12/08
    גࣜձࣾϥάβΠΞ தౡ ࣎

    View Slide

  2. RailsΞϓϦέʔγϣϯͷ
    ΞʔΩςΫνϟબ୒ͷ࿩

    View Slide

  3. ΞʔΩςΫνϟ
    ͸
    ΞϓϦέʔγϣϯʹґଘ
    ࠷ॳʹର৅ͷΞϓϦέʔγϣϯͷઆ໌Λ͠·͢

    View Slide

  4. LODQA BS
    Web
    e-mail
    LODQA BS
    DB
    DB
    DB
    ϑϩϯτΤϯυαʔόʔ όοΫΤϯυDB
    ݕࡧΤϯδϯ

    View Slide

  5. LODQA BSͷಛ௃
    ϑϩϯτΤϯυαʔόʔ ෳ਺
    όοΫΤϯυDB ෳ਺
    ݕࡧ࣌ؒ ਺ඵʙ10෼

    View Slide

  6. ԿΛݕࡧ͢Δͷ͔ʁ
    Ҩ఻ࢠ৘ใ
    όΠΦϒʔϜͷͱ͖ʹɺͨ͘͞Μղੳ͞Εͨ
    ۲ࢗ͠ݕࡧ͢ΔͨΊϦϯΫυσʔλͱͯ͠ެ։

    View Slide

  7. ϦϯΫυσʔλ
    άϥϑཧ࿦ͷάϥϑ
    ओޠ - ड़ޠ - ໨తޠ
    ཁૉΛͨͲͬͯݕࡧͰ͖Δ
    SPARQLͱSPARQLΤϯυϙΠϯτ

    View Slide

  8. ൚༻త
    ࢖͍͜ͳ͢ͷ͕೉͍͠

    View Slide

  9. ࢖͏ਓ
    ੜ໋Պֶ෼໺ͷݚڀऀ
    ܭࢉػՊֶ΍SPARQLͷઐ໳ՈͰͳ͍
    ྫ͑ΔͳΒ
    อݥ঎඼Λઃܭ͢Δਓ͕ɺੜSQLΛ࢖͍͜ͳͯ͠
    ࣄނ཰Λࢉग़

    View Slide

  10. ࣗવݴޠͰݕࡧ͍ͨ͠

    View Slide

  11. ӳจ͸ߏจղੳͰ͖Δ
    Which genes are associated with Endothelin receptor type B?
    genes Endothelin receptor type B
    associated with
    ߋʹURIʹม׵

    View Slide

  12. SPARQLΛੜ੒
    SELECT ?it1 ?st1 ?p01
    WHERE {
    ?it1 ?st1 .
    ?p01 ?it1 .
    FILTER (isIRI(?it1))
    FILTER (?p01 NOT IN (,
    ,
    ,
    ,
    ,
    ))
    FILTER (?st1 IN (,
    ,
    ,
    ,
    ,
    ))
    }
    LIMIT 10
    100ʙ1000ݸੜ੒͞ΕΔ

    View Slide

  13. ݕࡧۭؒ
    SPARQL͸άϥϑΛͨͲΔ
    ࢦ਺ؔ਺తʹݕࡧۭ͕ؒ૿͑Δ
    100 x 100 x 100 …
    ਺ສʙ10ԯϨίʔυˏone DB
    ओޠ- ड़ޠ ->໨తޠ
    =
    =
    GraphQLʹͪΐͬͱࣅ͍ͯΔ
    ओޠ- ड़ޠ ->໨తޠ
    ओޠ- ड़ޠ ->໨తޠ

    View Slide

  14. ݕࡧ࣌ؒྫ
    Which genes are associated with Endothelin receptor type B?
    => 40 ඵ
    What drugs are associated with strokes and arthrosis?
    => 10෼30ඵ

    View Slide

  15. ΞϓϦέʔγϣϯͷ࢓༷આ໌ऴΘΓ
    ͔͜͜ΒΞʔΩςΫνϟͷ࿩

    View Slide

  16. ΞϓϦέʔγϣϯͷಛ௃
    HTTPϦΫΤετͷ͸msʙඵ
    ݕࡧ͸਺ඵʙ਺෼
    ॲཧ࣌ؒͷΦʔμʔ͕ҧ͏

    View Slide

  17. Active Job
    Railsඪ४
    ඇಉظॲཧΠϯλϑΣʔε
    δϣϒͷ࣮ߦόοΫΤϯυ͕બ୒Մೳ
    delayed_job, sidekiq
    ActiveRecordͱDBͷؔ܎

    View Slide

  18. γʔέϯε
    ϑϩϯτΤϯυ
    ίϯτϩʔϥʔ
    DB
    ݕࡧδϣϒ
    HTTP
    ݕࡧ৘ใ
    Ϩεϙϯε
    ݕࡧ݁Ռ
    ݕࡧ݁ՌʢΩϟογϡʣ
    ݕࡧʢ਺ेඵʣ
    ʢ਺ेmsʣ

    View Slide

  19. ϛυϧ΢ΣΞͷબ୒
    DB
    SQLite3
    ActiveJob::QueueAdapter
    AsyncAdapter

    View Slide

  20. Why SQLIite3
    ϘτϧωοΫ͸όοΫΤϯυDB
    εέʔϧΞ΢τ͠ͳ͍
    ΞϓϦͱDBͷϓϩηεΛ෼͚Δඞཁ͕ͳ͍

    View Slide

  21. Why AsyncAdapter
    δϣϒͷӬଓԽ͕ෆཁ
    ݕࡧ్தͰΞϓϦέʔγϣϯΛ࠶ىಈͯ͠΋ɺ

    ݕࡧΛϦτϥΠ͠ͳ͍
    σϑΥϧτͷRails͸ඇಉظΩϡʔΛ࣮૷͠·͢ɻ͜Ε͸ɺΠϯ
    ϓϩηεͷεϨουϓʔϧͰδϣϒΛ࣮ߦ͠·͢ɻδϣϒ͸ඇಉ
    ظʹ࣮ߦ͞Ε·͕͢ɺ࠶ىಈ͢Δͱ͢΂ͯͷδϣϒ͸ࣦΘΕ·͢ɻ
    https://railsguides.jp/active_job_basics.html
    AsynAdapter͸Ωϡʔ͕Ұͭͱ͍͏ಛ௃΋͋Δ

    View Slide

  22. ϝϦοτ
    1ΞϓϦέʔγϣϯ1ϓϩηε
    ։ൃ؀ڥɺӡ༻؀ڥͷߏஙָ͕

    View Slide

  23. docker-compose
    ϦϙδτϦ͕ࢦఆͰ͖Δ






    ϞϊϨϙ͍Βͳ͍
    version: '3'
    services:
    lodqa_bs:
    build: https://github.com/lodqa/lodqa_bs.git
    lodqa_email_agent:
    build: .
    depends_on:
    - lodqa_bs

    View Slide

  24. Dockerfileͷίπ
    entory-point Ͱ db:migrate ͢Δ





    ιʔείʔυɾϑΝΠϧΛίϯςφʹίϐʔ͢Δ
    #!/bin/sh
    set -e
    if [ $1 = 'bin/rails' ] && [ $2 = 's' ] ; then
    rm -f ./tmp/pids/server.pid
    bin/rails db:migrate
    fi
    exec "[email protected]"
    RUN mkdir -p /usr/src/myapp
    WORKDIR /usr/src/myapp
    COPY . ./

    View Slide

  25. ͜͜·Ͱޫͷ࿩
    ͔͜͜Βҋͷ࿩

    View Slide

  26. Rail Wayͷ୺ͬ͜
    SQLLite3Λ࢖͍ͬͯΔਓʁ
    AsyncAdapterΛ࢖͍ͬͯΔਓʁ
    ஌ݟ͕গͳ͍
    ୺ͬ͜ײΛ࿩͠·͢

    View Slide

  27. SQLite3ͷ஫ҙ఺
    ಉ࣌ʹॻ͖ࠐΊͳ͍
    ಡΈࠐΈ͸OK
    SQLite3::BusyException ্͕͕ͬͯ͘Δ
    ActiveRecord͸έΞ͠ͳ͍
    ΞϓϦέʔγϣϯͰέΞ͢ΔͱActiveRecordͷந৅͕ഁΕΔ

    View Slide

  28. SQLite3Λ࢖͏ίπ
    DBίωΫγϣϯͷ্ݶΛ1ʹ͢Δ





    λΠϜΞ΢τ͸γϏΞʹͳΔ
    default: &default
    adapter: sqlite3
    pool: 1
    timeout: 5000
    config/database.yml

    View Slide

  29. AsyncAdapterͷ஫ҙ఺
    ඇಉظॲཧΛεϨουϓʔϧͰ࣮ݱ
    development؀ڥͷΫϥε୳ࡧͰΤϥʔ͕ى͖Δ
    ॥؀ࢀরݕग़ػೳ͕εϨουΞϯηʔϑ
    https://github.com/rails/rails/issues/18725#issuecomment-72091474
    2015೥͔Βط஌
    config.eager_load = true
    config/environments/development.rb

    View Slide

  30. DBίωΫγϣϯͷղ์
    ActiveRecordͷDBίωΫγϣϯΛऔಘɾղ์ͨ͜͠
    ͱ͕͋Δਓʁ
    ͳ͔ͥࣗಈతʹߦΘΕ͍ͯΔ

    View Slide

  31. ActiveRecordͷ
    DBίωΫγϣϯղ์ઓུ
    DBίωΫγϣϯʹɺ࣋ͪओͷεϨουΛ΋ͨͤΔ
    εϨου͕ऴ͍ྃͯͨ͠ΒɺDBίωΫγϣϯΛ࠶ར༻
    WebΞϓϦέʔγϣϯ͸HTTPϦΫΤετຖʹεϨουΛ࡞Δ
    ϨεϙϯεΛฦͨ͠ΒεϨου͸ऴྃ͢Δ
    WebΞϓϦέʔγϣϯ͸Ϩεϙϯεฦͨ͠ΒDBΛૢ࡞͠ͳ͍

    View Slide

  32. AsyncAdapterͷ஫ҙ఺
    ඇಉظॲཧΛεϨουϓʔϧͰ࣮ݱ
    εϨου͸ऴΘΒͳ͍
    ϓʔϧʹ໭ͬͯ࠶ར༻͞ΕΔ
    DBίωΫγϣϯ͸ղ์͞Εͳ͍

    View Slide

  33. AsyncAdapterΛ࢖͏ίπ
    DBΛखಈͰղ์͢Δ



    https://github.com/brandonhilkert/
    sucker_punch#activerecord-connection-pool-connections
    ط஌
    ActiveRecord::Base.connection_pool.checkin ApplicationRecord.connection
    ActiveRecord::Base.connection_pool.with_connection do
    # DBΛૢ࡞
    end

    View Slide

  34. ෳ߹ٕ
    SQLite3ͷίπͰDBίωΫγϣϯ਺ͷ্ݶΛ1ʹͨ͠
    DBૢ࡞Λ5ඵҎ಺ʹऴΘΒͤͳ͍ͱλΠϜΞ΢τ
    ࢖ͬͨΒଈղ์

    δϣϒ͕ऴΘΔ·Ͱ଴ͬͯ͸μϝ
    ͙͢ൃੜ͢ΔͷͰɺݕग़࿙Ε͸͠ʹ͍͘

    View Slide

  35. AsyncAdapterͷ஫ҙ఺̎
    Ωϡʔ͕Ұͭ
    ҰͭͷεϨουϓʔϧͰ͢΂ͯͷδϣϒΛॲཧ
    ༏ઌॱҐ੍͕ޚͰ͖ͳ͍
    https://github.com/rails/rails/blob/master/activejob/lib/active_job/queue_adapters/async_adapter.rb

    View Slide

  36. ஗͍δϣϒͱ଎͍δϣϒ
    ଎͍δϣϒΛઌʹ࣮ߦ͍ͨ͠
    ஗͍δϣϒ͕ऴΘΒͳ͍ͱ଎͍δϣϒΛ։࢝Ͱ͖ͳ͍
    ଎͍δϣϒઐ༻ͷΩϡʔΛ࡞Δ

    View Slide

  37. SuckerPunch
    https://github.com/brandonhilkert/sucker_punch
    Ωϡʔ͕δϣϒ͝ͱʹΘ͔Ε͍ͯΔ
    εϨουϓʔϧͰඇಉظॲཧΛ࣮ߦ
    https://api.rubyonrails.org/classes/ActiveJob/
    QueueAdapters.html
    Priorities͕No??

    View Slide

  38. SuckerPunchAdapter
    ΩϡʔͷࢦఆΛແࢹ͍ͯ͠Δ
    https://github.com/rails/rails/blob/master/activejob/lib/
    active_job/queue_adapters/sucker_punch_adapter.rb

    View Slide

  39. ϞϯΩʔύον
    module SuckerPunch
    module Job
    module ClassMethods
    def perform_async *_args, &block
    return unless SuckerPunch::RUNNING.true?
    queue = SuckerPunch::Queue.find_or_create to_s, num_workers, num_jobs_max
    queue.post { __run_perform(&block) }
    end
    def __run_perform
    SuckerPunch::Counter::Busy.new(to_s).increment
    result = yield
    SuckerPunch::Counter::Processed.new(to_s).increment
    result
    rescue StandardError => ex
    SuckerPunch::Counter::Failed.new(to_s).increment
    SuckerPunch.exception_handler.call ex, self, args
    ensure
    SuckerPunch::Counter::Busy.new(to_s).decrement
    end
    end
    end
    end
    module ActiveJob
    module QueueAdapters
    class SuckerPunchAdapter
    def enqueue job
    job.queue_name = job.class.to_s
    job.class.perform_async { Base.execute job.serialize }
    end
    end
    end
    end

    View Slide

  40. ·ͱΊ
    Railsͷந৅ΠϯλϑΣʔεྑ͍
    ActiveRecordɺActiveJob
    ϛυϧ΢ΣΞͷมߋ͕ՄೳʢθϩίετͰ͸ͳ͍ʣ
    ΞʔΩςΫνϟͷܾఆΛ஗ΒͤΒΕΔ
    ։ൃ؀ڥɺຊ൪؀ڥͷߏஙίετ͕ݮΒͤΔ
    ։ൃʹूதͰ͖Δ
    Ώͬ͘Γಈ͘ͱ଎͘ಈ͚Δ

    View Slide