1
1
package handlers
2
2
3
3
import (
4
+ "context"
4
5
"encoding/json"
5
6
"fmt"
7
+ "log"
6
8
"net/http"
7
9
"question-service/models"
8
10
"question-service/utils"
11
+
12
+ "cloud.google.com/go/firestore"
13
+ "google.golang.org/api/iterator"
9
14
)
10
15
11
16
func (s * Service ) CreateQuestion (w http.ResponseWriter , r * http.Request ) {
@@ -18,23 +23,71 @@ func (s *Service) CreateQuestion(w http.ResponseWriter, r *http.Request) {
18
23
return
19
24
}
20
25
21
- // Update database
22
- docRef , _ , err := s .Client .Collection ("questions" ).Add (ctx , map [string ]interface {}{
23
- "title" : question .Title ,
24
- "description" : question .Description ,
25
- "complexity" : question .Complexity ,
26
- "categories" : question .Categories ,
26
+ // Validation
27
+ // TODO: Duplicate checking for question name
28
+
29
+ // Reference to the document where we store the last ID
30
+ counterDocRef := s .Client .Collection ("counters" ).Doc ("questions" )
31
+
32
+ // Firestore transaction to implement auto-increment
33
+ err := s .Client .RunTransaction (ctx , func (ctx context.Context , tx * firestore.Transaction ) error {
34
+ doc , err := tx .Get (counterDocRef )
35
+ if err != nil {
36
+ return err
37
+ }
38
+
39
+ // Get the current value of the counter
40
+ currentCounter := doc .Data ()["count" ].(int64 )
41
+ newCounter := currentCounter + 1
42
+
43
+ // Update the counter in Firestore
44
+ if err := tx .Set (counterDocRef , map [string ]interface {}{
45
+ "count" : newCounter ,
46
+ }); err != nil {
47
+ return err
48
+ }
49
+
50
+ // Use the newCounter as the ID for the new document
51
+ docRef , _ , err := s .Client .Collection ("questions" ).Add (ctx , map [string ]interface {}{
52
+ "id" : newCounter ,
53
+ "title" : question .Title ,
54
+ "description" : question .Description ,
55
+ "complexity" : question .Complexity ,
56
+ "categories" : question .Categories ,
57
+ "createdAt" : firestore .ServerTimestamp ,
58
+ })
59
+ if err != nil {
60
+ http .Error (w , "Error adding question" , http .StatusInternalServerError )
61
+ return err
62
+ }
63
+
64
+ // Get data
65
+ doc , err = docRef .Get (ctx )
66
+ if err != nil {
67
+ if err != iterator .Done {
68
+ http .Error (w , "Question not found" , http .StatusNotFound )
69
+ return err
70
+ }
71
+ http .Error (w , "Failed to get question" , http .StatusInternalServerError )
72
+ return err
73
+ }
74
+
75
+ // Map data
76
+ question .DocRefID = doc .Ref .ID
77
+ if err := doc .DataTo (& question ); err != nil {
78
+ http .Error (w , "Failed to map question data" , http .StatusInternalServerError )
79
+ return err
80
+ }
81
+
82
+ return nil
27
83
})
28
84
if err != nil {
29
- http . Error ( w , "Error adding question " , http . StatusInternalServerError )
85
+ log . Fatalf ( "Trasaction failed: %v " , err )
30
86
return
31
87
}
32
88
33
- // Map data
34
- question .ID = docRef .ID
35
-
36
89
w .Header ().Set ("Content-Type" , "application/json" )
37
90
json .NewEncoder (w ).Encode (question )
38
91
39
- fmt .Fprintf (w , "Question with ID %s created successfully" , question .ID )
92
+ fmt .Fprintf (w , "Question with ID %s created successfully" , question .DocRefID )
40
93
}
0 commit comments