dataDownloadRequestKey.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package services
  2. import (
  3. "fmt"
  4. "net/url"
  5. "strings"
  6. "time"
  7. "fwh-toolbox-server/domain"
  8. )
  9. // Each document kind owns its content identity version. Bump only the affected
  10. // kind when its query, parsing, or stored content semantics change.
  11. var dataDownloadContentIdentityVersion = map[domain.DataDownloadKind]string{
  12. domain.DataDownloadPowerFlow: "v1",
  13. domain.DataDownloadMqttLog: "v1",
  14. domain.DataDownloadEventAlarm: "v1",
  15. domain.DataDownloadAlarmSnapshot: "v1",
  16. domain.DataDownloadEmsLog: "v1",
  17. domain.DataDownloadFaultRecord: "v2",
  18. domain.DataDownloadUpdateLog: "v1",
  19. }
  20. type dataDownloadRequestKeyField struct {
  21. name string
  22. value string
  23. }
  24. // buildDataDownloadRequestKey identifies the requested logical document. The
  25. // fields intentionally differ by kind so task-only or irrelevant parameters do
  26. // not reduce reuse between otherwise equivalent requests.
  27. func buildDataDownloadRequestKey(item *domain.DataDownloadItem) (string, error) {
  28. if item == nil {
  29. return "", fmt.Errorf("data download item is nil")
  30. }
  31. contentVersion, ok := dataDownloadContentIdentityVersion[item.Kind]
  32. if !ok {
  33. return "", fmt.Errorf("unsupported data download kind %q", item.Kind)
  34. }
  35. if item.SiteSN == "" {
  36. return "", fmt.Errorf("site SN is required for %s", item.Kind)
  37. }
  38. fields := []dataDownloadRequestKeyField{
  39. {name: "kind", value: string(item.Kind)},
  40. {name: "content_version", value: contentVersion},
  41. }
  42. addSite := func() {
  43. fields = append(fields, dataDownloadRequestKeyField{name: "site_sn", value: item.SiteSN})
  44. }
  45. addDate := func() error {
  46. if _, err := time.Parse(time.DateOnly, item.Date); err != nil {
  47. return fmt.Errorf("invalid data date %q for %s", item.Date, item.Kind)
  48. }
  49. fields = append(fields, dataDownloadRequestKeyField{name: "date", value: item.Date})
  50. return nil
  51. }
  52. addSubtype := func() error {
  53. if item.Subtype == "" {
  54. return fmt.Errorf("subtype is required for %s", item.Kind)
  55. }
  56. fields = append(fields, dataDownloadRequestKeyField{name: "subtype", value: item.Subtype})
  57. return nil
  58. }
  59. addTimezone := func() error {
  60. if item.Timezone == "" {
  61. return fmt.Errorf("timezone is required for %s", item.Kind)
  62. }
  63. fields = append(fields, dataDownloadRequestKeyField{name: "timezone", value: item.Timezone})
  64. return nil
  65. }
  66. switch item.Kind {
  67. case domain.DataDownloadPowerFlow, domain.DataDownloadEventAlarm, domain.DataDownloadAlarmSnapshot:
  68. addSite()
  69. if err := addDate(); err != nil {
  70. return "", err
  71. }
  72. if err := addTimezone(); err != nil {
  73. return "", err
  74. }
  75. case domain.DataDownloadMqttLog:
  76. addSite()
  77. if err := addDate(); err != nil {
  78. return "", err
  79. }
  80. if err := addSubtype(); err != nil {
  81. return "", err
  82. }
  83. if err := addTimezone(); err != nil {
  84. return "", err
  85. }
  86. case domain.DataDownloadEmsLog:
  87. addSite()
  88. if err := addDate(); err != nil {
  89. return "", err
  90. }
  91. if err := addSubtype(); err != nil {
  92. return "", err
  93. }
  94. case domain.DataDownloadFaultRecord:
  95. if item.DeviceSN == "" || item.DeviceType == "" {
  96. return "", fmt.Errorf("device SN and device type are required for %s", item.Kind)
  97. }
  98. fields = append(fields,
  99. dataDownloadRequestKeyField{name: "device_sn", value: item.DeviceSN},
  100. dataDownloadRequestKeyField{name: "device_type", value: item.DeviceType},
  101. )
  102. if err := addDate(); err != nil {
  103. return "", err
  104. }
  105. if err := addTimezone(); err != nil {
  106. return "", err
  107. }
  108. case domain.DataDownloadUpdateLog:
  109. addSite()
  110. }
  111. var key strings.Builder
  112. key.WriteString("dd-request-v1")
  113. for _, field := range fields {
  114. key.WriteByte('|')
  115. key.WriteString(field.name)
  116. key.WriteByte('=')
  117. key.WriteString(url.QueryEscape(field.value))
  118. }
  119. return key.String(), nil
  120. }