Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123 rindas
3.1KB

  1. package main
  2. import (
  3. "log"
  4. "time"
  5. )
  6. //openIDSession for a given openID
  7. // regardless howmany
  8. type openIDSession struct {
  9. openID string //who is this?
  10. count int // number of message in the Queue, channel
  11. jobs chan InWechatMsg
  12. data openIDSessionData //session data, that needs to be saved to disk
  13. }
  14. type workDone struct {
  15. openID string //which user
  16. consumed int //job done
  17. }
  18. //SessionManager manage all sessions
  19. type SessionManager struct {
  20. sessions map[string]openIDSession
  21. done chan workDone
  22. }
  23. //AllInMessage every API post that we get
  24. // we collect them and redistribute it according to
  25. // openID, all messages for a single openID will be
  26. // sequentially processed
  27. var AllInMessage <-chan InWechatMsg
  28. //a stand alone routine that manage all
  29. // live sessions
  30. // take all message and fanout to different openid handlers
  31. // for each openid, its message are manipulated in serial manner.
  32. func (m *SessionManager) startSessionManager(in <-chan InWechatMsg) {
  33. log.Println("session manager start..")
  34. for { //forever looping
  35. select {
  36. case msg := <-in:
  37. log.Printf("SessionMgr : incoming msg %s (%s)", msg.header.FromUserName, msg.header.MsgType)
  38. m.processIncomingMsg(msg)
  39. case d := <-m.done:
  40. log.Printf("SessionMgr : worker done openid=%s (done)=%d", d.openID, d.consumed)
  41. m.clearJobDone(d)
  42. }
  43. }
  44. }
  45. func (m *SessionManager) processIncomingMsg(v InWechatMsg) {
  46. openID := v.header.FromUserName
  47. s, found := m.sessions[openID]
  48. if !found { //create one
  49. s = m.createSession(openID)
  50. }
  51. s.jobs <- v //add job to channel
  52. s.count++
  53. log.Printf("Incoming message in queue %d", s.count)
  54. if s.count == 1 { //there is no worker thread working
  55. m.startJob(openID)
  56. } else if s.count <= 0 {
  57. log.Println(s)
  58. log.Fatal("new job added, but count = 0")
  59. }
  60. }
  61. func (m *SessionManager) createSession(openID string) openIDSession {
  62. s := openIDSession{}
  63. s.openID = openID
  64. s.count = 0
  65. s.jobs = make(chan InWechatMsg, 200)
  66. s.data, _ = getCurrentSesssion(openID) //either load or create new
  67. m.sessions[openID] = s //register it to memory
  68. return s
  69. }
  70. func (m *SessionManager) clearJobDone(d workDone) {
  71. s, found := m.sessions[d.openID]
  72. if found {
  73. s.count -= d.consumed
  74. if s.count == 0 { //no job to do
  75. //save session data to disk
  76. data := m.sessions[d.openID].data
  77. data.Save()
  78. //remove from memory
  79. m.destroySession(d.openID)
  80. } else if s.count > 0 {
  81. m.startJob(d.openID) //processing any newly coming jobs
  82. } else {
  83. log.Println(s)
  84. log.Fatal("session job count cannot be negative, problem session")
  85. }
  86. } else {
  87. log.Fatal("When job done, we canot find proper session")
  88. }
  89. }
  90. func (m *SessionManager) destroySession(openID string) {
  91. //close job channels
  92. s := m.sessions[openID]
  93. close(s.jobs)
  94. //delete it from memory
  95. delete(m.sessions, openID)
  96. }
  97. //worker thread
  98. func (m *SessionManager) startJob(openID string) {
  99. s := m.sessions[openID]
  100. jobFinished := workDone{openID, 0}
  101. //process all jobs in the channel
  102. for v := range s.jobs {
  103. log.Println(" Processing job..")
  104. log.Println(v)
  105. time.Sleep(5 * time.Second)
  106. jobFinished.consumed++
  107. }
  108. m.done <- jobFinished //notify parent that we have done
  109. return
  110. }