Skip to content

Commit

Permalink
Merge pull request #14 from 99designs/maybe-fix-concurrent-map-writes
Browse files Browse the repository at this point in the history
Protect against concurrent map writes in status command
  • Loading branch information
navitronic authored Feb 5, 2018
2 parents b68b252 + c31b337 commit 3d33096
Showing 1 changed file with 32 additions and 15 deletions.
47 changes: 32 additions & 15 deletions cli/smartling/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,49 @@ func MustStatus(remotefile, locale string) smartling.FileStatus {
return fs
}

type ProjectStatus map[string]map[string]smartling.FileStatus
type ProjectStatus struct {
sync.RWMutex
statuses map[string]map[string]smartling.FileStatus
}

func New() *ProjectStatus {
return &ProjectStatus{
statuses: make(map[string]map[string]smartling.FileStatus),
}
}

func (statuses ProjectStatus) Add(remotefile, locale string, fs smartling.FileStatus) {
_, ok := statuses[remotefile]
func (ps *ProjectStatus) Add(remotefile, locale string, fs smartling.FileStatus) {
ps.Lock()
defer ps.Unlock()

_, ok := ps.statuses[remotefile]
if !ok {
mm := make(map[string]smartling.FileStatus)
statuses[remotefile] = mm
ps.statuses[remotefile] = mm
}
statuses[remotefile][locale] = fs
ps.statuses[remotefile][locale] = fs
}

func (statuses ProjectStatus) AwaitingAuthorizationCount() int {
func (ps *ProjectStatus) AwaitingAuthorizationCount() int {
ps.RLock()
defer ps.RUnlock()

c := 0
for _, s := range statuses {
for _, s := range ps.statuses {
for _, status := range s {
c += status.AwaitingAuthorizationStringCount()
break
}
}

return c
}

func (statuses ProjectStatus) TotalStringsCount() int {
func (ps *ProjectStatus) TotalStringsCount() int {
ps.RLock()
defer ps.RUnlock()

c := 0
for _, s := range statuses {
for _, s := range ps.statuses {
for _, status := range s {
c += status.StringCount
break
Expand All @@ -51,9 +68,9 @@ func (statuses ProjectStatus) TotalStringsCount() int {
return c
}

func GetProjectStatus(prefix string, locales []string) ProjectStatus {
func GetProjectStatus(prefix string, locales []string) *ProjectStatus {
var wg sync.WaitGroup
statuses := ProjectStatus{}
statuses := New()

for _, projectFilepath := range ProjectConfig.Files() {
remoteFilePath := findIdenticalRemoteFileOrPush(projectFilepath, prefix)
Expand All @@ -71,7 +88,7 @@ func GetProjectStatus(prefix string, locales []string) ProjectStatus {
return statuses
}

func PrintProjectStatusTable(statuses ProjectStatus, locales []string) {
func PrintProjectStatusTable(ps *ProjectStatus, locales []string) {
// Format in columns
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)

Expand All @@ -82,10 +99,10 @@ func PrintProjectStatusTable(statuses ProjectStatus, locales []string) {
}
fmt.Fprint(w, "\n")

for projectFilepath, _ := range statuses {
for projectFilepath, _ := range ps.statuses {
aa := false
for _, locale := range locales {
status := statuses[projectFilepath][locale]
status := ps.statuses[projectFilepath][locale]
if !aa {
fmt.Fprintf(w, "%7d", status.AwaitingAuthorizationStringCount())
aa = true
Expand Down

0 comments on commit 3d33096

Please sign in to comment.