예제 #1
0
func (self *mysqlMessageCache) retrieveOnce(service, username string, since time.Time) (msgs []*rpc.MessageContainer, err error) {
	self.lock.RLock()
	defer self.lock.RUnlock()
	rows, err := self.getMultiMsgStmt.Query(service, username, since.Unix(), time.Now().Unix())
	if err != nil {
		err = fmt.Errorf("Data base error: %v; query multi-msg error", err)
		return
	}
	defer rows.Close()

	msgs = make([]*rpc.MessageContainer, 0, 128)
	for rows.Next() {
		mc := new(rpc.MessageContainer)
		var data []byte
		var createTime int64
		err = rows.Scan(&mc.Id, &mc.SenderService, &mc.Sender, &createTime, &data)
		if err != nil {
			return
		}
		mc.Message = new(rpc.Message)
		err = json.Unmarshal(data, mc.Message)
		if err != nil {
			return
		}
		mc.Birthday = time.Unix(createTime, 0)
		msgs = append(msgs, mc)
	}
	return
}
예제 #2
0
func (self *serverConn) writeDigest(mc *rpc.MessageContainer, extra map[string]string, sz int) error {
	digest := &proto.Command{
		Type: proto.CMD_DIGEST,
	}
	params := [4]string{fmt.Sprintf("%v", sz), mc.Id}

	if mc.FromUser() {
		params[2] = mc.Sender
		params[3] = mc.SenderService
		digest.Params = params[:4]
	} else {
		digest.Params = params[:2]
	}

	msg := mc.Message
	header := make(map[string]string, len(extra)+len(msg.Header))
	self.digestFielsLock.Lock()
	defer self.digestFielsLock.Unlock()

	for _, f := range self.digestFields {
		if len(msg.Header) > 0 {
			if v, ok := msg.Header[f]; ok {
				header[f] = v
			}
		}
		if len(extra) > 0 {
			if v, ok := extra[f]; ok {
				header[f] = v
			}
		}
	}
	if len(header) > 0 {
		digest.Message = &rpc.Message{
			Header: header,
		}
	}

	compress := self.shouldCompress(digest.Message.Size())
	return self.cmdio.WriteCommand(digest, compress)
}
예제 #3
0
func (self *mysqlMessageCache) CacheMessage(service, username string, mc *rpc.MessageContainer, ttl time.Duration) (id string, err error) {
	data, err := json.Marshal(mc.Message)
	if err != nil {
		return
	}

	if mc.Id == "" {
		id = randomId()
		mc.Id = id
	} else {
		id = mc.Id
	}

	uniqid := getUniqMessageId(service, username, id)
	if len(uniqid) > maxMessageIdLength {
		err = fmt.Errorf("message id length is greater than %v characters", maxMessageIdLength)
		return
	}

	if len(username) > maxUsernameLength {
		err = fmt.Errorf("user %v's name is too long", username)
		return
	}
	if len(mc.Sender) > maxUsernameLength {
		err = fmt.Errorf("user %v's name is too long", mc.Sender)
		return
	}
	if len(service) > maxServicenameLength {
		err = fmt.Errorf("service %v's name is too long", service)
		return
	}
	if len(mc.SenderService) > maxServicenameLength {
		err = fmt.Errorf("service %v's name is too long", mc.SenderService)
		return
	}

	now := time.Now()
	mc.Birthday = now
	deadline := now.Add(ttl)
	if ttl < 1*time.Second {
		// max possible value for int64
		deadline = time.Unix(0, 0)
	}
	var result sql.Result

	err = self.expBackoffRetry(3, 2, func() error {
		result, err = self.cacheStmt.Exec(uniqid, id, service, username, mc.SenderService, mc.Sender, now.Unix(), deadline.Unix(), data)
		return err
	})
	if err != nil {
		err = fmt.Errorf("Data base error: %v; insert error", err)
		return
	}
	n, err := result.RowsAffected()
	if err != nil {
		return
	}
	if n != 1 {
		err = fmt.Errorf("affected %v rows, which is weird", n)
		return
	}
	return
}