Skip to content

Commit be5aa35

Browse files
committed
Add mutexes, remote deprecated ioutil usage, move profiler to init
1 parent 95be735 commit be5aa35

1 file changed

Lines changed: 42 additions & 11 deletions

File tree

StreamStatus.go

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import (
44
"bytes"
55
"encoding/json"
66
"fmt"
7-
"io/ioutil"
7+
"io"
88
"net/http"
99
"os"
1010
"strings"
11+
"sync"
1112
"time"
1213

1314
"cloud.google.com/go/profiler"
@@ -35,6 +36,7 @@ type StreamersRepo struct {
3536
language string
3637
game string
3738
client *helix.Client
39+
mutex *sync.Mutex
3840
}
3941

4042
// NoChangeNeededError is a struct for a custom error handler
@@ -50,6 +52,8 @@ func (e *NoChangeNeededError) Error() string {
5052

5153
// gitPush pushes the repository to github and return and error.
5254
func (s *StreamersRepo) gitPush() error {
55+
s.mutex.Lock()
56+
defer s.mutex.Unlock()
5357
err := s.repo.Push(&git.PushOptions{
5458
RemoteName: "origin",
5559
Auth: s.auth,
@@ -62,8 +66,11 @@ func (s *StreamersRepo) gitPush() error {
6266
}
6367

6468
// gitCommit makes a commit to the repository and returns an error.
69+
// The Below code has a race condition. Suggest a fix:
6570
func (s *StreamersRepo) gitCommit() error {
71+
s.mutex.Lock()
6672
w, err := s.repo.Worktree()
73+
s.mutex.Unlock()
6774
if err != nil {
6875
return err
6976
}
@@ -73,26 +80,32 @@ func (s *StreamersRepo) gitCommit() error {
7380
} else {
7481
commitMessage = fmt.Sprintf("☠️ %s has gone offline! [no ci]", s.streamer)
7582
}
83+
s.mutex.Lock()
7684
_, err = w.Commit(commitMessage, &git.CommitOptions{
7785
Author: &object.Signature{
7886
Name: "🤖 STATUSS (Seriously Totally Automated Twitch Updating StreamStatus)",
7987
Email: "goproslowyo+statuss@users.noreply.github.com",
8088
When: time.Now(),
8189
},
8290
})
91+
s.mutex.Unlock()
8392
if err != nil {
8493
return err
8594
}
95+
s.mutex.Lock()
8696
commit, err := s.getHeadCommit()
97+
s.mutex.Unlock()
8798
if err != nil {
8899
return err
89100
}
90-
log.Println(commit)
101+
log.Printf("Current HEAD commit: %s\n", commit)
91102
return nil
92103
}
93104

94105
// gitAdd adds the index file to the repository and returns an error.
95106
func (s *StreamersRepo) gitAdd() error {
107+
s.mutex.Lock()
108+
defer s.mutex.Unlock()
96109
w, err := s.repo.Worktree()
97110
if err != nil {
98111
return err
@@ -126,18 +139,20 @@ func (s *StreamersRepo) getHeadCommit() (string, error) {
126139
func (s *StreamersRepo) getRepo() error {
127140
directory := strings.SplitN(s.url, "/", 5)[4]
128141
repo, err := git.PlainClone(directory, false, &git.CloneOptions{
129-
// The intended use of a GitHub personal access token is in replace of your password
130-
// because access tokens can easily be revoked.
142+
// The intended use of a GitHub personal access token is to replace passwords because
143+
// access tokens can easily be revoked.
131144
// https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/
132145
Auth: s.auth,
133146
URL: s.url,
134147
// We're discarding the stdout out here. If you'd like to see it toggle
135148
// `Progress` to something like os.Stdout.
136-
Progress: ioutil.Discard,
149+
Progress: io.Discard,
137150
})
138151

139152
if err == nil {
153+
s.mutex.Lock()
140154
s.repo = repo
155+
s.mutex.Unlock()
141156
return nil
142157
}
143158
// Check if the error is that the repo exists and if it is on disk open it.
@@ -160,20 +175,26 @@ func (s *StreamersRepo) getRepo() error {
160175
ReferenceName: "HEAD",
161176
RemoteName: "origin",
162177
})
178+
s.mutex.Lock()
163179
s.repo = repo
180+
s.mutex.Unlock()
164181
return nil
165182
}
166183

167184
// writeFile writes given text and returns an error.
168185
func (s *StreamersRepo) writefile(activeText, inactiveText string) error {
169186
bytesToWrite := []byte(activeText)
170-
err := ioutil.WriteFile(s.indexFilePath, bytesToWrite, 0644)
187+
s.mutex.Lock()
188+
err := os.WriteFile(s.indexFilePath, bytesToWrite, 0644)
189+
s.mutex.Unlock()
171190
if err != nil {
172191
return err
173192
}
174193

175194
bytesToWrite = []byte(inactiveText)
176-
err = ioutil.WriteFile(s.inactiveFilePath, bytesToWrite, 0644)
195+
s.mutex.Lock()
196+
err = os.WriteFile(s.inactiveFilePath, bytesToWrite, 0644)
197+
s.mutex.Unlock()
177198
if err != nil {
178199
return err
179200
}
@@ -220,8 +241,10 @@ func (s *StreamersRepo) updateStreamStatus() error {
220241
}
221242
}
222243
}
244+
s.mutex.Lock()
223245
s.indexMdText = strings.Join(indexMdLines, "\n")
224246
s.inactiveMdText = strings.Join(inactiveMdLines, "\n")
247+
s.mutex.Unlock()
225248

226249
return nil
227250
}
@@ -250,14 +273,18 @@ func (s *StreamersRepo) generateStreamerLine(otherInfo string) string {
250273
// readFile reads in a slice of bytes from the provided path and returns a string or an error.
251274
func (s *StreamersRepo) readFile() error {
252275
// Read index.md
276+
s.mutex.Lock()
253277
markdownText, err := os.ReadFile(s.indexFilePath)
278+
s.mutex.Unlock()
254279
if err != nil {
255280
return err
256281
}
257282
s.indexMdText = string(markdownText)
258283

259284
// Read inactive.md
285+
s.mutex.Lock()
260286
iMarkdownText, err := os.ReadFile(s.inactiveFilePath)
287+
s.mutex.Unlock()
261288
if err != nil {
262289
return err
263290
}
@@ -324,7 +351,7 @@ type eventSubNotification struct {
324351
// eventsubStatus takes and http Request and ResponseWriter to handle the incoming webhook request.
325352
func (s *StreamersRepo) eventsubStatus(w http.ResponseWriter, r *http.Request) {
326353
// Read the request body.
327-
body, err := ioutil.ReadAll(r.Body)
354+
body, err := io.ReadAll(r.Body)
328355
if err != nil {
329356
log.Println(err)
330357
return
@@ -452,16 +479,19 @@ func lineIndex(arr []string, item string) int {
452479
return 1
453480
}
454481

455-
// main do the work.
456-
func main() {
482+
// init function for the profiler.
483+
func init() {
457484
// Setup profiler.
458485
cfg := profiler.Config{
459486
Service: "streamstatus",
460-
ServiceVersion: "1.0.0",
487+
ServiceVersion: "1.1.0",
461488
}
462489
// Profiler initialization, best done as early as possible.
463490
profiler.Start(cfg)
491+
}
464492

493+
// main do the work.
494+
func main() {
465495
// Setup file and repo paths.
466496
var repoUrl string
467497
if len(os.Getenv("SS_GH_REPO")) == 0 {
@@ -509,6 +539,7 @@ func main() {
509539
repoPath: repoPath,
510540
url: repoUrl,
511541
client: client,
542+
mutex: &sync.Mutex{},
512543
}
513544
port := ":8080"
514545
// Google Cloud Run defaults to 8080. Their platform

0 commit comments

Comments
 (0)