Slide 1

Slide 1 text

(PͰ࡞Δ େྔϓϩηε؅ཧػߏ ໟརܒଠ

Slide 2

Slide 2 text

‣ 'VTJD$P -UE ‣ ൃҊऀϓϩμΫτΦʔφʔ ‣ *P5ܥͷडୗҊ݅΋ ‣ (P 3VCZ "84 403"$0. ໟརܒଠʢ΋͏Γ͚͍ͨʣ

Slide 3

Slide 3 text

Slide 4

Slide 4 text

ࣗࣾαʔϏε

Slide 5

Slide 5 text

ࣗࣾαʔϏε डୗ։ൃ 8FCαΠτ &$αΠτ FUD ۀ຿ΞϓϦ ίϯαϧ "3 Ϋϥ΢υ *P5 'JO5FDI "* ΠϯλϥΫςΟϒίϯςϯπ εϚϗΞϓϦ

Slide 6

Slide 6 text

ࣗࣾαʔϏε डୗ։ൃ 8FCαΠτ &$αΠτ FUD ۀ຿ΞϓϦ ίϯαϧ "3 Ϋϥ΢υ *P5 'JO5FDI "* ΠϯλϥΫςΟϒίϯςϯπ εϚϗΞϓϦ ύʔτφʔ

Slide 7

Slide 7 text

ࠓ೔͓࿩͍ͨ͜͠ͱ

Slide 8

Slide 8 text

ͷલʹʜ

Slide 9

Slide 9 text

ͬͯͳʹʁ

Slide 10

Slide 10 text

*P5։ൃऀ޲͚ ٙࣅσʔλੜ੒αʔϏε

Slide 11

Slide 11 text

*P5ͷ࿩

Slide 12

Slide 12 text

Ϟϊ͕ Thing

Slide 13

Slide 13 text

Πϯλʔωοτܦ༝Ͱ Thing

Slide 14

Slide 14 text

αʔόʹσʔλΛૹΓ Backend Thing D a t a

Slide 15

Slide 15 text

ղੳͨ͠Γͯ͠ Backend Thing D a t a

Slide 16

Slide 16 text

Կ͔͢Δ Backend Thing D a t a

Slide 17

Slide 17 text

*P5ͷ࿩ ͓ΘΓ

Slide 18

Slide 18 text

*P5 ։ൃ͠·͢

Slide 19

Slide 19 text

ςετ͍ͨ͠ Backend Thing D a t a

Slide 20

Slide 20 text

σʔλૹͬͯ΄͍͠ Backend Thing D a t a

Slide 21

Slide 21 text

Ͱ΋

Slide 22

Slide 22 text

Ϟϊʹͩͬͯ ౎߹͸͋Δ

Slide 23

Slide 23 text

͑͐ͬɺ ։ൃʹ൒೥΋͔͔Δͷʂʁ

Slide 24

Slide 24 text

͑͐ͬɺ ϗϯτʹյ͞ͳ͍ͱ Τϥʔσʔλग़ͤͳͷʂʁ

Slide 25

Slide 25 text

ෛՙࢼݧ༻ʹ୆ ཉ͍͚͠Ͳʜ ݸສԁʂʁ

Slide 26

Slide 26 text

ෛՙࢼݧ༻ʹ୆ ༻ҙ͚ͨ͠Ͳʜ ୭͕ૢ࡞͢Δͷ͜Εʂʁ

Slide 27

Slide 27 text

ςετʹࠔΔ

Slide 28

Slide 28 text

ͦ͏ͩʂ

Slide 29

Slide 29 text

γϛϡϨʔλʔΛ࡞Ζ͏ʂ Backend Simulator D a t a

Slide 30

Slide 30 text

΍͹͍ɺ ϦϦʔεʹؒʹ߹Θͳ͍ʂ

Slide 31

Slide 31 text

೉͗ͯ͢͠ ʓʓ͞Μ ࡞ͬͨਓ ͔͠ ಈ͔ͤͳ͍ʜ

Slide 32

Slide 32 text

ٱ͠ͿΓʹಈ͔ͨ͠Β શવಈ͔ͳ͍ʜ

Slide 33

Slide 33 text

ͦ͜Ͱ

Slide 34

Slide 34 text

ࢥ͍Ͳ͓ΓʹͳΔϞϊ Backend D a t a

Slide 35

Slide 35 text

͍ͭͰ΋ ཉ͍͠σʔλΛ ཉ͍͠ྔ͚ͩ ૹͬͯ͘ΕΔʂ

Slide 36

Slide 36 text

͏Ε͍͠

Slide 37

Slide 37 text

ը໘Πϝʔδ ࢥ͍௨ΓͷϑΥʔϚοτͰ+40/σʔλΛੜ੒ Ծ૝σόΠεͷεςʔλεͱͦͷมԽΛ೚ҙʹઃఆ ͞·͟·ͳ࣌ܥྻσʔλੜ੒ػೳ

Slide 38

Slide 38 text

ͷͬ͘͟Γͨ͠࢓૊Έ

Slide 39

Slide 39 text

PublicSubnet PrivateSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker Mock Mock Mock Mock Mock WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞

Slide 40

Slide 40 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞ mockૢ࡞JobΛ ൃߦ PrivateSubnet Mock Mock Mock Mock Mock

Slide 41

Slide 41 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ PrivateSubnet Mock Mock Mock Mock Mock Mock WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞

Slide 42

Slide 42 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞

Slide 43

Slide 43 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock mockىಈ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞

Slide 44

Slide 44 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock mockىಈ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞

Slide 45

Slide 45 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker ίϯιʔϧͰ mockΛૢ࡞ mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock mockىಈ Mock Mock [ mock ] Go੡όΠφϦ͔Βཱͯͨ Ծ૝σόΠε໾ϓϩηε [ tower ] Go੡όΠφϦ͔Βཱͯͨ mock؅ཧϓϩηε

Slide 46

Slide 46 text

ࠓ೔͓࿩͍ͨ͜͠ͱ վΊͯʂ

Slide 47

Slide 47 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock mockىಈ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞

Slide 48

Slide 48 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock ͳΜͰϓϩηεʁ ͳΜͰGoʁ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞

Slide 49

Slide 49 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock ͳΜͰϓϩηεʁ ͳΜͰGoʁ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞ Ͳ͏΍ͬͯ େྔͷϓϩηεΛૢ࡞ʁ

Slide 50

Slide 50 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ Քಇঢ়گɾϩάૹ৴ PrivateSubnet Mock Mock Mock Mock Mock Mock ͳΜͰϓϩηεʁ ͳΜͰGoʁ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞ Ͳ͏΍ͬͯ େྔͷϓϩηεΛૢ࡞ʁ mockͷࢮ׆؂ࢹ͸ Ͳ͏ͯ͠Δͷʁ ઃఆϑΝΠϧ όΠφϦΛDL

Slide 51

Slide 51 text

PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ Քಇঢ়گɾϩάૹ৴ PrivateSubnet Mock Mock Mock Mock Mock Mock ͳΜͰϓϩηεʁ ͳΜͰGoʁ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞ Ͳ͏΍ͬͯ େྔͷϓϩηεΛૢ࡞ʁ mockͷࢮ׆؂ࢹ͸ Ͳ͏ͯ͠Δͷʁ όΠφϦͷ ߋ৽͸ Ͳ͏͢Δͷʁ

Slide 52

Slide 52 text

ͳΜͰϓϩηεʁ ͳΜͰ(P

Slide 53

Slide 53 text

‣ NPDLJT αʔόʔ߽՚͗͢Δʜ ίϯςφएׯ໘౗ͩ͠ɺίϯςφԽ͢Δඞཁ΋ͳ͍ ϓϩηεͪΐ͏Ͳ͍͍ʂ εϨουσόοάେมͦ͏ɺڞ౗Εͦ͠͏ ͳΜͰϓϩηεʁ

Slide 54

Slide 54 text

‣ αʔόʔʹԿ΋Πϯετʔϧͨ͘͠ͳ͍ ͨͱ͑͹3VCZͩͱ3VCZΛΠϯετʔϧ͢Δඞཁ͕ʜ ‣ γϯάϧόΠφϦʹ͢Ε͹ஔ͚ͩ͘Ͱىಈ͕Ͱ͖Δ ‣ γϯάϧόΠφϦ͕Ͱ͖Δ΍ͭͰָͦ͠͏ͳͷ ‣ ͱ͍͑͹(Pʂ ओ؍ ͳΜͰ(Pʁ

Slide 55

Slide 55 text

‣ ίʔυͷن໛ ςετআ͘ NPDL໿ߦ UPXFS໿ߦ ͪͳΈʹ

Slide 56

Slide 56 text

େྔNPDLͷૢ࡞

Slide 57

Slide 57 text

‣ ϑΝΠϧϕʔεͰͷૢ࡞ ಛఆͷσΟϨΫτϦʹϑΝΠϧΛஔ͔ΕͨͷΛݕ஌ͯ͠ॲཧΛߦ͏ ૢ࡞͕ඞཁͳ෼͚ͩϑΝΠϧΛஔ͚͹͍͍ NPDLͷૢ࡞ NPDLىಈ NPDLఀࢭ ىಈτϦΨʔ
 ϑΝΠϧઃஔ tower͕ݕ஌͠ mockΛىಈ ఀࢭτϦΨʔ
 ϑΝΠϧઃஔ ֤mock༻ ఀࢭτϦΨʔ
 ϑΝΠϧઃஔ mock͕ݕ஌͠ ࣗݾফ໓

Slide 58

Slide 58 text

‣ ݪ࢝త͚ͩͲγϯϓϧͰ৴པੑ΋ߴ͘΍Γ΍͍͢ Կ΋Πϯετʔϧ͠ͳ͍͍ͯ͘ ॲཧ͕׬ྃͨ͠ޙʹϑΝΠϧΛফ͢Α͏ʹ͓͚ͯ͠͹ɺ
 ΋͠UPXFS్͕தͰ࠶ىಈͯ͠΋ϑΝΠϧΛݟΕ͹ϨδϡʔϜͰ͖Δ ‣ ͦͷଞͷ͔ͬ͜Α͛͞ͳ΍Γํ͸ΊΜͲ͍͘͞ؾ͕͢Δ )551αʔόʔ 1VC4VC2VFVF NPDLͷૢ࡞ ૹ৴ࣦഊͨ͠ͱ͖ͷ࠶ૹʜ ૢ࡞׬ྃલʹUPXFS͕ࢮΜͩ৔߹ʜ

Slide 59

Slide 59 text

‣ https://github.com/fsnotify/fsnotify ‣ ϑΝΠϧมߋݕ஌ϥΠϒϥϦ GTOPUJGZ

Slide 60

Slide 60 text

GTOPUJGZ watcher, err := fsnotify.NewWatcher() defer watcher.Close() err = watcher.Add("path/to/trigger/directory") // ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } }

Slide 61

Slide 61 text

watcher, err := fsnotify.NewWatcher() defer watcher.Close() err = watcher.Add("path/to/trigger/directory") // ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } } GTOPUJGZ ؂ࢹର৅ͷσΟϨΫτϦΛઃఆ func (w *Watcher) Add(name string) error

Slide 62

Slide 62 text

watcher, err := fsnotify.NewWatcher() defer watcher.Close() err = watcher.Add("path/to/trigger/directory") // ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } } GTOPUJGZ ؂ࢹର৅ͷσΟϨΫτϦΛઃఆ func (w *Watcher) Add(name string) error type Event struct { Name string // Πϕϯτ͕͋ͬͨ file/directory Op Op // ૢ࡞छผΛද͢Ϗοτྻ }

Slide 63

Slide 63 text

GTOPUJGZ watcher, err := fsnotify.NewWatcher() defer watcher.Close() err = watcher.Add("path/to/trigger/directory") // ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } } ؂ࢹର৅ͷσΟϨΫτϦΛઃఆ func (w *Watcher) Add(name string) error ev.OpʹϏοτϚεΫΛ͔͚Δ͜ͱͰૢ࡞छผΛ֬ೝ type Op uint32 const ( Create Op = 1 << iota Write Remove Rename Chmod ) type Event struct { Name string // Πϕϯτ͕͋ͬͨ file/directory Op Op // ૢ࡞छผΛද͢Ϗοτྻ }

Slide 64

Slide 64 text

watcher, err := fsnotify.NewWatcher() defer watcher.Close() err = watcher.Add("path/to/trigger/directory") // ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } } GTOPUJGZ ؂ࢹର৅ͷσΟϨΫτϦΛઃఆ func (w *Watcher) Add(name string) error ev.OpʹϏοτϚεΫΛ͔͚Δ͜ͱͰૢ࡞छผΛ֬ೝ type Op uint32 const ( Create Op = 1 << iota Write Remove Rename Chmod ) type Event struct { Name string // Πϕϯτ͕͋ͬͨ file/directory Op Op // ૢ࡞छผΛද͢Ϗοτྻ } sleepೖΕͯ΋ͪΌΜͱશ෦௨஌ͯ͘͠ΕΔͷͰ QueueͬΆ͍ײ͡ʹͳΔ

Slide 65

Slide 65 text

NPDLͷࢮ׆؂ࢹ

Slide 66

Slide 66 text

‣ NPDLఀࢭॲཧͰਖ਼ৗʹఀࢭͰ͖͔ͨ NPDL༻ͷఀࢭτϦΨʔϑΝΠϧΛઃஔ ࣗવఀࢭ w ࠷େՔಇ࣌ؒܦա w ఀࢭεςʔλε΁ͷભҠ ‣ NPDL͕ҟৗऴ͍ྃͯ͠ͳ͍͔ NPDL͕ಥવͷࢮΛܴ͑ΔՄೳੑ΋θϩͰ͸ͳ͍ ద੾ʹݕ஌ɾ௨஌͠ͳ͚Ε͹ NPDLͷࢮ׆؂ࢹ

Slide 67

Slide 67 text

‣ NPDLఀࢭॲཧͰਖ਼ৗʹఀࢭͰ͖͔ͨ NPDL༻ͷఀࢭτϦΨʔϑΝΠϧΛઃஔ ࣗવఀࢭ w ࠷େՔಇ࣌ؒܦա w ఀࢭεςʔλε΁ͷભҠ ‣ NPDL͕ҟৗऴ͍ྃͯ͠ͳ͍͔ NPDL͕ಥવͷࢮΛܴ͑ΔՄೳੑ΋θϩͰ͸ͳ͍ ద੾ʹݕ஌ɾ௨஌͠ͳ͚Ε͹ NPDLͷࢮ׆؂ࢹ ϓϩηεͷ ঢ়ଶมԽΛ؂ࢹ

Slide 68

Slide 68 text

NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ processExitChannel chan int func (t *Tower) mockExec(mock MockCode, version string, ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PidΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid)

Slide 69

Slide 69 text

processExitChannel chan int func (t *Tower) mockExec(mock MockCode, version string, ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PidΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid) NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ ϓϩηεىಈޙɺgoroutineΛ૸Βͤͯ؂ࢹ͢Δ (ىಈ͍ͯ͠Δmockͷ਺͚ͩgoroutineΛ૸Β͍ͤͯΔ)

Slide 70

Slide 70 text

NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ processExitChannel chan int func (t *Tower) mockExec(mock MockCode, version string, ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PidΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid) ϓϩηεىಈޙɺgoroutineΛ૸Βͤͯ؂ࢹ͢Δ (ىಈ͍ͯ͠Δmockͷ਺͚ͩgoroutineΛ૸Β͍ͤͯΔ) WNOHANGΦϓγϣϯ: ঢ়ଶมԽ͕ىͬͨ͜ࢠϓϩηε͕ͳ͍৔߹ʹ͙͢ʹ෮ؼ

Slide 71

Slide 71 text

processExitChannel chan int func (t *Tower) mockExec(mock MockCode, version string, ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PidΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid) NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ ϓϩηεىಈޙɺgoroutineΛ૸Βͤͯ؂ࢹ͢Δ (ىಈ͍ͯ͠Δmockͷ਺͚ͩgoroutineΛ૸Β͍ͤͯΔ) WNOHANGΦϓγϣϯ: ঢ়ଶมԽ͕ىͬͨ͜ࢠϓϩηε͕ͳ͍৔߹ʹ͙͢ʹ෮ؼ status.ExitStatus()Ͱҟৗऴྃ֬ೝ΋ͨ͠Γ͢Δ

Slide 72

Slide 72 text

processExitChannel chan int func (t *Tower) mockExec(mock MockCode, version string, ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PIDΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid) NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ ϓϩηεىಈޙɺgoroutineΛ૸Βͤͯ؂ࢹ͢Δ (ىಈ͍ͯ͠Δmockͷ਺͚ͩgoroutineΛ૸Β͍ͤͯΔ) ऴྃͨ͠ΒprocessExitChannelʹ௨஌ WNOHANGΦϓγϣϯ: ঢ়ଶมԽ͕ىͬͨ͜ࢠϓϩηε͕ͳ͍৔߹ʹ͙͢ʹ෮ؼ status.ExitStatus()Ͱҟৗऴྃ֬ೝ΋ͨ͠Γ͢Δ

Slide 73

Slide 73 text

NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ // ϝΠϯϧʔϓ for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ case pid := <-processExitChannel: mock := mockProcessTable[pid] // ऴྃޙͷ͓ย෇͚΋Ζ΋Ζ delete(mockProcessTable, pid) } }

Slide 74

Slide 74 text

‣ NPDLఀࢭॲཧͰਖ਼ৗʹఀࢭͰ͖͔ͨ NPDL༻ͷఀࢭτϦΨʔϑΝΠϧΛઃஔ ࣗવఀࢭ w ࠷େՔಇ࣌ؒܦա w ఀࢭεςʔλε΁ͷભҠ ‣ NPDL͕ҟৗऴ͍ྃͯ͠ͳ͍͔ NPDL͕ಥવͷࢮΛܴ͑ΔՄೳੑ΋θϩͰ͸ͳ͍ ద੾ʹݕ஌ɾ௨஌͠ͳ͚Ε͹ NPDLͷࢮ׆؂ࢹ ϓϩηεͷ ঢ়ଶมԽΛ؂ࢹ ఀࢭτϦΨʔϑΝΠϧͱ ಈ࡞தͷϓϩηεΛൺֱ

Slide 75

Slide 75 text

ఀࢭτϦΨʔϑΝΠϧͷফԽ֬ೝ ticker := time.NewTicker(tickerIntervalMsec) defer ticker.Stop() // ϝΠϯϧʔϓ for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ case tickTime := <-ticker.C: // τϦΨʔϑΝΠϧ͕͋Δͷʹ࢒͍ͬͯΔϓϩηεΛ֬ೝ t.processLeftMock(tickTime) } } func (t *Tower) processLeftMock(cur time.Time) { for mock, term := range t.terminateTable { if cur.Before(term.triggeredAt.Add(ForceTerminateTime)) { continue } pid, processExist := t.mockTable[mock] proc, err := os.FindProcess(pid) err = proc.Signal(os.Kill) delete(t.terminateTable, mock) } }

Slide 76

Slide 76 text

ఀࢭτϦΨʔϑΝΠϧͷফԽ֬ೝ ticker := time.NewTicker(tickerIntervalMsec) defer ticker.Stop() // ϝΠϯϧʔϓ for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ case tickTime := <-ticker.C: // τϦΨʔϑΝΠϧ͕͋Δͷʹ࢒͍ͬͯΔϓϩηεΛ֬ೝ t.processLeftMock(tickTime) } } func (t *Tower) processLeftMock(cur time.Time) { for mock, term := range t.terminateTable { if cur.Before(term.triggeredAt.Add(ForceTerminateTime)) { continue } pid, processExist := t.mockTable[mock] proc, err := os.FindProcess(pid) err = proc.Signal(os.Kill) delete(t.terminateTable, mock) } } tickerΛ࢖ͬͯఆظతʹະফԽτϦΨʔϑΝΠϧΛ֬ೝ

Slide 77

Slide 77 text

ఀࢭτϦΨʔϑΝΠϧͷফԽ֬ೝ ticker := time.NewTicker(tickerIntervalMsec) defer ticker.Stop() // ϝΠϯϧʔϓ for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ case tickTime := <-ticker.C: // τϦΨʔϑΝΠϧ͕͋Δͷʹ࢒͍ͬͯΔϓϩηεΛ֬ೝ t.processLeftMock(tickTime) } } func (t *Tower) processLeftMock(cur time.Time) { for mock, term := range t.terminateTable { if cur.Before(term.triggeredAt.Add(ForceTerminateTime)) { continue } pid, processExist := t.mockTable[mock] proc, err := os.FindProcess(pid) err = proc.Signal(os.Kill) delete(t.terminateTable, mock) } } tickerΛ࢖ͬͯఆظతʹະফԽτϦΨʔϑΝΠϧΛ֬ೝ ઃஔޙҰఆ͕࣌ؒܦաͨ͠΋ͷͷΈ͕֬ೝର৅

Slide 78

Slide 78 text

ఀࢭτϦΨʔϑΝΠϧͷফԽ֬ೝ ticker := time.NewTicker(tickerIntervalMsec) defer ticker.Stop() // ϝΠϯϧʔϓ for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ case tickTime := <-ticker.C: // τϦΨʔϑΝΠϧ͕͋Δͷʹ࢒͍ͬͯΔϓϩηεΛ֬ೝ t.processLeftMock(tickTime) } } func (t *Tower) processLeftMock(cur time.Time) { for mock, term := range t.terminateTable { if cur.Before(term.triggeredAt.Add(ForceTerminateTime)) { continue } pid, processExist := t.mockTable[mock] proc, err := os.FindProcess(pid) err = proc.Signal(os.Kill) delete(t.terminateTable, mock) } } tickerΛ࢖ͬͯఆظతʹະফԽτϦΨʔϑΝΠϧΛ֬ೝ ઃஔޙҰఆ͕࣌ؒܦաͨ͠΋ͷͷΈ͕֬ೝର৅ ϓϩηεڧ੍ऴྃ

Slide 79

Slide 79 text

όΠφϦͷߋ৽

Slide 80

Slide 80 text

‣ NPDL Քಇத͸ߋ৽ෆཁ ಉ͡ઃఆͰಈ͖ଓ͚ΔͷͰ ىಈ࣌ʹ࠷৽൛ͷόΠφϦΛ࣋ͬͯ͘Ε͹0, ‣ UPXFS NPDL͕ՔಇதͰ΋ߋ৽͍ͨ͠ ࠶ىಈ چUPXFSΛఀࢭ৽UPXFSΛىಈ Ͱ͖ΔΑ͏ʹ͓ͯ͘͠ NPDL؂ࢹঢ়گͷϨδϡʔϜΛ͕Μ͹Δʂ όΠφϦͷߋ৽

Slide 81

Slide 81 text

‣ ࠶ىಈखॱ <چ>UPXFSͷ࠶ىಈτϦΨʔϑΝΠϧͷݕ஌ <چ>τϦΨʔϑΝΠϧʹॻ͔Ε͍ͯΔόʔδϣϯΛ4͔Β%-ͯ͠ىಈ <چ>ऴྃ <৽>NPDLͷ؂ࢹঢ়گΛϨδϡʔϜ ‣ ϨδϡʔϜ͠ͳ͍ͱ͍͚ͳ͍΋ͷ NPDL$PEFͱ1*%Λؔ࿈෇͚ΔNBQ NPDLϓϩηεΛ؂ࢹ͢ΔHPSPVUJOF UPXFSͷ࠶ىಈ

Slide 82

Slide 82 text

࠶ىಈτϦΨʔϑΝΠϧݕ஌dऴྃ // ϝΠϯϧʔϓ for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ఆظॲཧͱ͔ case ev := <-t.towerReboot.Events: if (ev.Op & fsnotify.Create) == 0 || (base != towerRebootName) { continue } rebootStrs, err := ioutil.ReadFile(ev.Name) reboot := strings.Split(strings.TrimSpace(string(rebootStrs)), " ") // ࠶ىಈ࣌ʹόΠφϦ͕ଘࡏ͠ͳ͍৔߹͸μ΢ϯϩʔυͯ͘͠Δ(ུ) // ৽towerىಈ _, err = os.StartProcess(binPath, args, attr) // ϝΠϯϧʔϓ͔Βൈ͚Δ return } }

Slide 83

Slide 83 text

࠶ىಈτϦΨʔϑΝΠϧݕ஌dऴྃ // ϝΠϯϧʔϓ for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ఆظॲཧͱ͔ case ev := <-t.towerReboot.Events: if (ev.Op & fsnotify.Create) == 0 || (base != towerRebootName) { continue } rebootStrs, err := ioutil.ReadFile(ev.Name) reboot := strings.Split(strings.TrimSpace(string(rebootStrs)), " ") // ࠶ىಈ࣌ʹόΠφϦ͕ଘࡏ͠ͳ͍৔߹͸μ΢ϯϩʔυͯ͘͠Δ(ུ) // ৽towerىಈ _, err = os.StartProcess(binPath, args, attr) // ϝΠϯϧʔϓ͔Βൈ͚Δ return } } ࠶ىಈτϦΨʔϑΝΠϧͷ࡞੒ΠϕϯτҎ֎͸ແࢹ

Slide 84

Slide 84 text

࠶ىಈτϦΨʔϑΝΠϧݕ஌dऴྃ // ϝΠϯϧʔϓ for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ఆظॲཧͱ͔ case ev := <-t.towerReboot.Events: if (ev.Op & fsnotify.Create) == 0 || (base != towerRebootName) { continue } rebootStrs, err := ioutil.ReadFile(ev.Name) reboot := strings.Split(strings.TrimSpace(string(rebootStrs)), " ") // ࠶ىಈ࣌ʹόΠφϦ͕ଘࡏ͠ͳ͍৔߹͸μ΢ϯϩʔυͯ͘͠Δ(ུ) // ৽towerىಈ _, err = os.StartProcess(binPath, args, attr) // ϝΠϯϧʔϓ͔Βൈ͚Δ return } } ࠶ىಈτϦΨʔϑΝΠϧͷ࡞੒ΠϕϯτҎ֎͸ແࢹ τϦΨʔϑΝΠϧͷத਎ΛݺΜͰόʔδϣϯΛऔಘ

Slide 85

Slide 85 text

࠶ىಈτϦΨʔϑΝΠϧݕ஌dऴྃ // ϝΠϯϧʔϓ for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ఆظॲཧͱ͔ case ev := <-t.towerReboot.Events: if (ev.Op & fsnotify.Create) == 0 || (base != towerRebootName) { continue } rebootStrs, err := ioutil.ReadFile(ev.Name) reboot := strings.Split(strings.TrimSpace(string(rebootStrs)), " ") // ࠶ىಈ࣌ʹόΠφϦ͕ଘࡏ͠ͳ͍৔߹͸μ΢ϯϩʔυͯ͘͠Δ(ུ) // ৽towerىಈ _, err = os.StartProcess(binPath, args, attr) // ϝΠϯϧʔϓ͔Βൈ͚Δ return } } ࠶ىಈτϦΨʔϑΝΠϧͷ࡞੒ΠϕϯτҎ֎͸ແࢹ τϦΨʔϑΝΠϧͷத਎ΛݺΜͰόʔδϣϯΛऔಘ ϝΠϯϧʔϓ͔Βൈ͚Δͱͦͷ··ऴྃ

Slide 86

Slide 86 text

NPDL؂ࢹঢ়گͷϨδϡʔϜ func NewTower() *Tower { // ͍Ζ͍ΖॳظԽ(ུ) // PIDϑΝΠϧΛऔಘ pidFiles, err := filepath.Glob(filepath.Join(t.PidsDir(), "mk-*")) for _, pidFile := range pidFiles { mock := MockCode(filepath.Base(pidFile)) // PIDϑΝΠϧ͔ΒPIDΛಡΈऔΓ pidStr, err := ioutil.ReadFile(pidFile) pid, err := strconv.Atoi(strings.TrimSpace(string(pidStr))) // PID͔Β࣮ࡍͷϓϩηεΛݟ͚ͭͯอଘ proc, err := os.FindProcess(pid) t.mockProcessTable[pid] = mock // ϓϩηεऴྃ௨஌goroutineΛ௥Ճ go func(t *Tower, mock MockCode, pid int) { // (ུ) }(&t, mock, pid) } }

Slide 87

Slide 87 text

NPDL؂ࢹঢ়گͷϨδϡʔϜ func NewTower() *Tower { // ͍Ζ͍ΖॳظԽ(ུ) // PIDϑΝΠϧΛऔಘ pidFiles, err := filepath.Glob(filepath.Join(t.PidsDir(), "mk-*")) for _, pidFile := range pidFiles { mock := MockCode(filepath.Base(pidFile)) // PIDϑΝΠϧ͔ΒPIDΛಡΈऔΓ pidStr, err := ioutil.ReadFile(pidFile) pid, err := strconv.Atoi(strings.TrimSpace(string(pidStr))) // PID͔Β࣮ࡍͷϓϩηεΛݟ͚ͭͯอଘ proc, err := os.FindProcess(pid) t.mockProcessTable[pid] = mock // ϓϩηεऴྃ௨஌goroutineΛ௥Ճ go func(t *Tower, mock MockCode, pid int) { // (ུ) }(&t, mock, pid) } } ֤mock͸ىಈ࣌ʹPIDϑΝΠϧΛ࡞Δ

Slide 88

Slide 88 text

NPDL؂ࢹঢ়گͷϨδϡʔϜ func NewTower() *Tower { // ͍Ζ͍ΖॳظԽ(ུ) // PIDϑΝΠϧΛऔಘ pidFiles, err := filepath.Glob(filepath.Join(t.PidsDir(), "mk-*")) for _, pidFile := range pidFiles { mock := MockCode(filepath.Base(pidFile)) // PIDϑΝΠϧ͔ΒPIDΛಡΈऔΓ pidStr, err := ioutil.ReadFile(pidFile) pid, err := strconv.Atoi(strings.TrimSpace(string(pidStr))) // PID͔Β࣮ࡍͷϓϩηεΛݟ͚ͭͯอଘ proc, err := os.FindProcess(pid) t.mockProcessTable[pid] = mock // ϓϩηεऴྃ௨஌goroutineΛ௥Ճ go func(t *Tower, mock MockCode, pid int) { // (ུ) }(&t, mock, pid) } } ֤mock͸ىಈ࣌ʹPIDϑΝΠϧΛ࡞Δ লུͯ͠Δ͚Ͳɺ ϓϩηε͕ݟ͔ͭΒͳ͔ͬͨΒPIDϑΝΠϧΛ࡟আ

Slide 89

Slide 89 text

·ͱΊ

Slide 90

Slide 90 text

‣ ɹɹʹ͓͍ͯɺ(PΛ࢖ͬͯ
 େྔͷϓϩηεΛͲͷΑ͏ʹ؅ཧ͍ͯ͠Δ͔Λ঺հ ͦ΋ͦ΋ͳΜͰϓϩηεʁͳΜͰ(P ϑΝΠϧϕʔεͷNPDLૢ࡞ NPDLͷࢮ׆؂ࢹ όΠφϦͷߋ৽ ‣ ʮ໌೔͔Β࢖͑ΔʯΑ͏ͳ಺༰Ͱ͸ͳ͍͸͚ͣͩͲɺ
 ָ͠ΜͰ΋Β͑ͨͳΒ޾͍Ͱ͢ ‣ (Pͨͷ͍͠ʂ ·ͱΊ

Slide 91

Slide 91 text

ΛҰॹʹ ։ൃͯ͘͠ΕΔ஥ؒΛืूதʂ ͝ڵຯ͋Δํ͸ໟར·Ͱʂ Go Ruby AWS IoT ΋ͬͱ͏·͘΍ΕΔʂ ͓΋͠Ζͦ͏ʂ @Fukuoka