func handleUnregistration(dest common.Destination) common.SyncServiceError {
	if common.Configuration.NodeType == common.ESS {
		return &notificationHandlerError{"Error: Only CSS can handle the unregistration"}
	}
	if !common.IsValidName(dest.DestType) || !common.IsValidName(dest.DestID) {
		return &notificationHandlerError{("Error in handleUnregistration: destination contains invalid characters")}
	}
	if trace.IsLogging(logger.DEBUG) {
		trace.Debug("Handling unregistration of %s %s\n", dest.DestType, dest.DestID)
	}
	var err common.SyncServiceError
	metadataList := make([]common.MetaData, 0)
	if metadataList, err = Store.RetrieveAllObjectsAndUpdateDestinationListForDestination(dest.DestOrgID, dest.DestType, dest.DestID); err != nil {
		trace.Error("Failed to retrieve objects for destination and update destinations for those objects %s %s %s, Error: %s\n", dest.DestOrgID, dest.DestType, dest.DestID, err)
		return err
	}
	if trace.IsLogging(logger.DEBUG) {
		trace.Debug("Get %d Metadata for destination %s %s %s: \n", len(metadataList), dest.DestOrgID, dest.DestType, dest.DestID)
		for _, meta := range metadataList {
			trace.Debug("%s/%s\n", meta.ObjectType, meta.ObjectID)
		}
	}
	if trace.IsLogging(logger.DEBUG) {
		trace.Debug("Deleting notification records for destination %s %s %s: \n", dest.DestOrgID, dest.DestType, dest.DestID)
	}
	if err := Store.DeleteNotificationRecords(dest.DestOrgID, "", "", dest.DestType, dest.DestID); err != nil {
		trace.Error("Failed to delete notification records for destination %s %s %s, Error: %s\n", dest.DestOrgID, dest.DestType, dest.DestID, err)
		return err
	}
	for _, metaData := range metadataList {
		removeNotificationChunksInfo(metaData, metaData.OriginType, metaData.OriginID)
	}
	if err := Store.DeleteDestination(dest.DestOrgID, dest.DestType, dest.DestID); err != nil {
		trace.Error("Failed to delete destination %s %s %s, Error: %s\n", dest.DestOrgID, dest.DestType, dest.DestID, err)
		return err
	}
	return nil
}
CSS: handle ESS unregister
package communications
import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"os"
	"sort"
	"sync"
	"time"
	"github.com/open-horizon/edge-sync-service/common"
	"github.com/open-horizon/edge-sync-service/core/dataURI"
	"github.com/open-horizon/edge-sync-service/core/leader"
	"github.com/open-horizon/edge-sync-service/core/storage"
	"github.com/open-horizon/edge-utilities/logger"
	"github.com/open-horizon/edge-utilities/logger/log"
	"github.com/open-horizon/edge-utilities/logger/trace"
)
type notificationHandlerError struct {
	message string
}
func (e *notificationHandlerError) Error() string {
	return e.message
}
type notificationChunksInfo struct {
	maxRequestedOffset int64
	maxReceivedOffset  int64
	receivedDataSize   int64
	chunkResendTimes   map[int64]int64  
	chunksReceived     []byte           
	chunkSize          int
	resendTime         int64
}
var registerAsNew bool
var notificationLock sync.RWMutex
var consumedLock sync.RWMutex
var dataChunksLocks common.Locks
var notificationChunks map[string]notificationChunksInfo
func init() {
	notificationChunks = make(map[string]notificationChunksInfo)
	dataChunksLocks = *common.NewLocks("notification")
}
func handleRegistration(dest common.Destination, persistentStorage bool) common.SyncServiceError {
	if common.Configuration.NodeType == common.ESS {
		return &notificationHandlerError{"ESS cannot register other services"}
	}
	if !common.IsValidName(dest.DestType) || !common.IsValidName(dest.DestID) {
		return &notificationHandlerError{("Error in handleRegistration: destination contains invalid characters")}
	}
	if trace.IsLogging(logger.TRACE) {
		trace.Trace("Handling registration of %s %s\n", dest.DestType, dest.DestID)
	}
	reconnection, err := Store.DestinationExists(dest.DestOrgID, dest.DestType, dest.DestID)
	if err != nil {
		return &notificationHandlerError{fmt.Sprintf("Error in handleRegistration: failed to check destination's existence. Error: %s\n", err)}
	}
	if !reconnection {
		if err := Comm.RegisterAsNew(dest); err != nil {
			return &notificationHandlerError{"Error in handleRegistration: failed to send register as new notification. Error: " + err.Error()}
		}
		return &ignoredByHandler{}
	}
	if err := Store.StoreDestination(dest); err != nil {
		return &notificationHandlerError{fmt.Sprintf("Error in handleRegistration: failed to store destination. Error: %s\n", err)}
	}
	if err := Comm.RegisterAck(dest); err != nil {
		return &notificationHandlerError{fmt.Sprintf("Error in handleRegistration: failed to send ack. Error: %s\n", err)}
	}
	if log.IsLogging(logger.INFO) {
		log.Info("Reconnection of: %s %s %s\n", dest.DestOrgID, dest.DestType, dest.DestID)
	}
	if err := resendNotificationsForDestination(dest, !persistentStorage); err != nil {
		return &notificationHandlerError{fmt.Sprintf("Error in handleRegistration. Error: %s\n", err)}
	}
	return nil
}
func handleRegisterNew(dest common.Destination, persistentStorage bool) common.SyncServiceError {
	if common.Configuration.NodeType == common.ESS {
		return &notificationHandlerError{"ESS cannot register other services"}
	}
	if !common.IsValidName(dest.DestType) || !common.IsValidName(dest.DestID) {
		return &notificationHandlerError{("Error in handleRegisterNew: destination contains invalid characters")}
	}
	if trace.IsLogging(logger.TRACE) {
		trace.Trace("Handling registration of a new ESS: %s %s\n", dest.DestType, dest.DestID)
	}
	if err := Store.StoreDestination(dest); err != nil {
		return &notificationHandlerError{fmt.Sprintf("Error in handleRegisterNew: failed to store destination. Error: %s\n", err)}
	}
	if log.IsLogging(logger.INFO) {
		log.Info("New destination: %s %s %s", dest.DestOrgID, dest.DestType, dest.DestID)
	}
	if err := Comm.RegisterAck(dest); err != nil {
		return &notificationHandlerError{fmt.Sprintf("Error in handleRegisterNew: failed to send ack. Error: %s\n", err)}
	}
	resend := common.ResendDelivered
	if persistentStorage {
		resend = common.ResendUndelivered
	}
	objects, err := Store.RetrieveObjects(dest.DestOrgID, dest.DestType, dest.DestID, resend)
	if err != nil {
		return err
	}
	if len(objects) > 0 {
		destinations := make([]common.Destination, 1)
		destinations[0] = dest
		for _, metaData := range objects {
			notificationsInfo, err := PrepareUpdateNotification(metaData, destinations)
			if err == nil {
				if err := SendNotifications(notificationsInfo); err != nil {
					return err
				}
			} else {
				return err
			}
		}
	}
	return nil
}