func (cm *PollingProjectConfigManager) SyncConfig() {
	var e error
	var code int
	var respHeaders http.Header
	var datafile []byte
	closeMutex := func(e error) {
		cm.err = e
		cm.configLock.Unlock()
	}
	url := fmt.Sprintf(cm.datafileURLTemplate, cm.sdkKey)
	if cm.lastModified != "" {
		lastModifiedHeader := utils.Header{Name: ModifiedSince, Value: cm.lastModified}
		datafile, respHeaders, code, e = cm.requester.Get(url, lastModifiedHeader)
	} else {
		datafile, respHeaders, code, e = cm.requester.Get(url)
	}
	if e != nil {
		msg := "unable to fetch fresh datafile"
		cm.logger.Warning(msg)
		cm.configLock.Lock()
		if code == http.StatusForbidden {
			closeMutex(Err403Forbidden)
			return
		}
		closeMutex(errors.New(fmt.Sprintf("%s, reason (http status code): %s", msg, e.Error())))
		return
	}
	if code == http.StatusNotModified {
		cm.logger.Debug("The datafile was not modified and won't be downloaded again")
		return
	}
	cm.configLock.Lock()
	lastModified := respHeaders.Get(LastModified)
	if lastModified != "" {
		cm.lastModified = lastModified
	}
	projectConfig, err := datafileprojectconfig.NewDatafileProjectConfig(datafile, logging.GetLogger(cm.sdkKey, "NewDatafileProjectConfig"))
	if err != nil {
		cm.logger.Warning("failed to create project config")
		closeMutex(errors.New("unable to parse datafile"))
		return
	}
	var previousRevision string
	if cm.projectConfig != nil {
		previousRevision = cm.projectConfig.GetRevision()
	}
	if projectConfig.GetRevision() == previousRevision {
		cm.logger.Debug(fmt.Sprintf("No datafile updates. Current revision number: %s", cm.projectConfig.GetRevision()))
		closeMutex(nil)
		return
	}
	err = cm.setConfig(projectConfig)
	closeMutex(err)
	if err == nil {
		cm.logger.Debug(fmt.Sprintf("New datafile set with revision: %s. Old revision: %s", projectConfig.GetRevision(), previousRevision))
		cm.sendConfigUpdateNotification()
	}
}
SyncConfig downloads datafile and updates projectConfig
package config
import (
	"context"
	"fmt"
	"net/http"
	"sync"
	"time"
	"github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig"
	"github.com/optimizely/go-sdk/pkg/logging"
	"github.com/optimizely/go-sdk/pkg/notification"
	"github.com/optimizely/go-sdk/pkg/registry"
	"github.com/optimizely/go-sdk/pkg/utils"
	"github.com/pkg/errors"
)
const DefaultPollingInterval = 5 * time.Minute  
const ModifiedSince = "If-Modified-Since"
const LastModified = "Last-Modified"
const DatafileURLTemplate = "https://cdn.optimizely.com/datafiles/%s.json"
const AuthDatafileURLTemplate = "https://config.optimizely.com/datafiles/auth/%s.json"
var Err403Forbidden = errors.New("unable to fetch fresh datafile (consider rechecking SDK key), status code: 403 Forbidden")
type PollingProjectConfigManager struct {
	datafileURLTemplate string
	initDatafile        []byte
	lastModified        string
	notificationCenter  notification.Center
	pollingInterval     time.Duration
	requester           utils.Requester
	sdkKey              string
	logger              logging.OptimizelyLogProducer
	datafileAccessToken string
	configLock       sync.RWMutex
	err              error
	projectConfig    ProjectConfig
	optimizelyConfig *OptimizelyConfig
}
type OptionFunc func(*PollingProjectConfigManager)
func WithRequester(requester utils.Requester) OptionFunc {
	return func(p *PollingProjectConfigManager) {
		p.requester = requester
	}
}
func WithDatafileURLTemplate(datafileTemplate string) OptionFunc {
	return func(p *PollingProjectConfigManager) {
		p.datafileURLTemplate = datafileTemplate
	}
}
func WithPollingInterval(interval time.Duration) OptionFunc {
	return func(p *PollingProjectConfigManager) {
		p.pollingInterval = interval
	}
}
func WithInitialDatafile(datafile []byte) OptionFunc {
	return func(p *PollingProjectConfigManager) {
		p.initDatafile = datafile
	}
}
func WithDatafileAccessToken(datafileAccessToken string) OptionFunc {
	return func(p *PollingProjectConfigManager) {
		p.datafileAccessToken = datafileAccessToken
	}
}