You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.3 KiB

  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "fmt"
  7. "code.gitea.io/gitea/modules/indexer"
  8. "code.gitea.io/gitea/modules/log"
  9. "code.gitea.io/gitea/modules/setting"
  10. "code.gitea.io/gitea/modules/util"
  11. )
  12. // issueIndexerUpdateQueue queue of issue ids to be updated
  13. var issueIndexerUpdateQueue chan int64
  14. // InitIssueIndexer initialize issue indexer
  15. func InitIssueIndexer() {
  16. indexer.InitIssueIndexer(populateIssueIndexer)
  17. issueIndexerUpdateQueue = make(chan int64, setting.Indexer.UpdateQueueLength)
  18. go processIssueIndexerUpdateQueue()
  19. }
  20. // populateIssueIndexer populate the issue indexer with issue data
  21. func populateIssueIndexer() error {
  22. batch := indexer.IssueIndexerBatch()
  23. for page := 1; ; page++ {
  24. repos, _, err := SearchRepositoryByName(&SearchRepoOptions{
  25. Page: page,
  26. PageSize: RepositoryListDefaultPageSize,
  27. OrderBy: SearchOrderByID,
  28. Private: true,
  29. Collaborate: util.OptionalBoolFalse,
  30. })
  31. if err != nil {
  32. return fmt.Errorf("Repositories: %v", err)
  33. }
  34. if len(repos) == 0 {
  35. return batch.Flush()
  36. }
  37. for _, repo := range repos {
  38. issues, err := Issues(&IssuesOptions{
  39. RepoIDs: []int64{repo.ID},
  40. IsClosed: util.OptionalBoolNone,
  41. IsPull: util.OptionalBoolNone,
  42. })
  43. if err != nil {
  44. return err
  45. }
  46. if err = IssueList(issues).LoadComments(); err != nil {
  47. return err
  48. }
  49. for _, issue := range issues {
  50. if err := batch.Add(issue.update()); err != nil {
  51. return err
  52. }
  53. }
  54. }
  55. }
  56. }
  57. func processIssueIndexerUpdateQueue() {
  58. batch := indexer.IssueIndexerBatch()
  59. for {
  60. var issueID int64
  61. select {
  62. case issueID = <-issueIndexerUpdateQueue:
  63. default:
  64. // flush whatever updates we currently have, since we
  65. // might have to wait a while
  66. if err := batch.Flush(); err != nil {
  67. log.Error(4, "IssueIndexer: %v", err)
  68. }
  69. issueID = <-issueIndexerUpdateQueue
  70. }
  71. issue, err := GetIssueByID(issueID)
  72. if err != nil {
  73. log.Error(4, "GetIssueByID: %v", err)
  74. } else if err = batch.Add(issue.update()); err != nil {
  75. log.Error(4, "IssueIndexer: %v", err)
  76. }
  77. }
  78. }
  79. func (issue *Issue) update() indexer.IssueIndexerUpdate {
  80. comments := make([]string, 0, 5)
  81. for _, comment := range issue.Comments {
  82. if comment.Type == CommentTypeComment {
  83. comments = append(comments, comment.Content)
  84. }
  85. }
  86. return indexer.IssueIndexerUpdate{
  87. IssueID: issue.ID,
  88. Data: &indexer.IssueIndexerData{
  89. RepoID: issue.RepoID,
  90. Title: issue.Title,
  91. Content: issue.Content,
  92. Comments: comments,
  93. },
  94. }
  95. }
  96. // updateNeededCols whether a change to the specified columns requires updating
  97. // the issue indexer
  98. func updateNeededCols(cols []string) bool {
  99. for _, col := range cols {
  100. switch col {
  101. case "name", "content":
  102. return true
  103. }
  104. }
  105. return false
  106. }
  107. // UpdateIssueIndexerCols update an issue in the issue indexer, given changes
  108. // to the specified columns
  109. func UpdateIssueIndexerCols(issueID int64, cols ...string) {
  110. if updateNeededCols(cols) {
  111. UpdateIssueIndexer(issueID)
  112. }
  113. }
  114. // UpdateIssueIndexer add/update an issue to the issue indexer
  115. func UpdateIssueIndexer(issueID int64) {
  116. select {
  117. case issueIndexerUpdateQueue <- issueID:
  118. default:
  119. go func() {
  120. issueIndexerUpdateQueue <- issueID
  121. }()
  122. }
  123. }