<commit_before>package userSystem

import (
	"database/sql"
	"errors"
	log "github.com/Sirupsen/logrus"
	"github.com/oxfeeefeee/appgo"
)

const (
	pushBatchSize = 450
)

func (u *UserSystem) PushTo(users []appgo.Id, content *appgo.PushData) {
	doPush := func(ids []appgo.Id) {
		if tokens, err := u.GetPushTokens(ids); err != nil {
			log.WithFields(log.Fields{
				"users": ids,
				"error": err,
			}).Errorln("failed to GetPushTokens")
		} else {
			for prov, data := range tokens {
				pusher := u.DefaultPusher
				if p, ok := u.Pushers[prov]; ok {
					pusher = p
				}
				for plat, tokens := range data {
					pusher.PushNotif(plat, tokens, content)
				}
			}
		}
	}
	for i := 0; i < len(users); i += pushBatchSize {
		end := i + pushBatchSize
		if end > len(users) {
			end = len(users)
		}
		doPush(users[i:end])
	}
}

func (u *UserSystem) SetPushToken(id appgo.Id, platform appgo.Platform,
	provider, token string) error {
	if provider == "" || token == "" {
		return errors.New("bad push provider or token")
	}
	user := &UserModel{Id: id}
	update := &UserModel{
		Platform:     platform,
		PushProvider: sql.NullString{provider, true},
		PushToken:    sql.NullString{token, true},
	}
	return u.db.Model(user).Updates(update).Error
}

func (u *UserSystem) GetPushTokens(ids []appgo.Id) (map[string]map[appgo.Platform][]string, error) {
	var users []*UserModel
	if err := u.db.Select("platform, push_provider, push_token").
		Where("id in (?)", ids).Find(&users).Error; err != nil {
		return nil, err
	}
	ret := make(map[string]map[appgo.Platform][]string)
	for _, user := range users {
		plat, prov, token := user.Platform, user.PushProvider.String, user.PushToken.String
		if plat != 0 && prov != "" && token != "" {
			if _, ok := ret[prov]; !ok {
				ret[prov] = make(map[appgo.Platform][]string)
			}
			if _, ok := ret[prov][plat]; !ok {
				ret[prov][plat] = make([]string, 0)
			}
			ret[prov][plat] = append(ret[prov][plat], token)
		}
	}
	return ret, nil
}
<commit_msg>add recover for push function<commit_after>package userSystem

import (
	"database/sql"
	"errors"
	log "github.com/Sirupsen/logrus"
	"github.com/oxfeeefeee/appgo"
)

const (
	pushBatchSize = 450
)

func (u *UserSystem) PushTo(users []appgo.Id, content *appgo.PushData) {
	defer func() {
		if r := recover(); r != nil {
			log.Errorln("Push notification paniced: ", r)
		}
	}()
	doPush := func(ids []appgo.Id) {
		if tokens, err := u.GetPushTokens(ids); err != nil {
			log.WithFields(log.Fields{
				"users": ids,
				"error": err,
			}).Errorln("failed to GetPushTokens")
		} else {
			for prov, data := range tokens {
				pusher := u.DefaultPusher
				if p, ok := u.Pushers[prov]; ok {
					pusher = p
				}
				for plat, tokens := range data {
					pusher.PushNotif(plat, tokens, content)
				}
			}
		}
	}
	for i := 0; i < len(users); i += pushBatchSize {
		end := i + pushBatchSize
		if end > len(users) {
			end = len(users)
		}
		doPush(users[i:end])
	}
}

func (u *UserSystem) SetPushToken(id appgo.Id, platform appgo.Platform,
	provider, token string) error {
	if provider == "" || token == "" {
		return errors.New("bad push provider or token")
	}
	user := &UserModel{Id: id}
	update := &UserModel{
		Platform:     platform,
		PushProvider: sql.NullString{provider, true},
		PushToken:    sql.NullString{token, true},
	}
	return u.db.Model(user).Updates(update).Error
}

func (u *UserSystem) GetPushTokens(ids []appgo.Id) (map[string]map[appgo.Platform][]string, error) {
	var users []*UserModel
	if err := u.db.Select("platform, push_provider, push_token").
		Where("id in (?)", ids).Find(&users).Error; err != nil {
		return nil, err
	}
	ret := make(map[string]map[appgo.Platform][]string)
	for _, user := range users {
		plat, prov, token := user.Platform, user.PushProvider.String, user.PushToken.String
		if plat != 0 && prov != "" && token != "" {
			if _, ok := ret[prov]; !ok {
				ret[prov] = make(map[appgo.Platform][]string)
			}
			if _, ok := ret[prov][plat]; !ok {
				ret[prov][plat] = make([]string, 0)
			}
			ret[prov][plat] = append(ret[prov][plat], token)
		}
	}
	return ret, nil
}

{'fraction_non_alphanumeric': 0.17259873232569478, 'fraction_numerical': 0.0029254022428083864, 'mean_word_length': 3.553829078801332, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '68350', 'n_tokens_mistral': 1678, 'n_tokens_neox': 1533, 'n_words': 351}