Écrit par Mark Tse, développeur de logiciels, Développement de plate-forme D2L
À partir de la version 10.7.5, les administrateurs peuvent planifier des extraits différentiels en plus des extraits complets, ce qui permet des rapports plus fréquents. Ces extraits différentiels sont générés à des intervalles définis et contiennent des données nouvellement disponibles depuis que les extraits différentiels précédents ont été générés.
Dans cet article, nous nous appuierons sur l’exemple de code dans Ensembles de données Brightspace - Exemple de client sans tête (non interactif) pour montrer comment tirer parti des API d’application pour maintenir une base de données à jour avec des extraits différentiels. Le code source de cet article est disponible sur GitHub.
Différences d’API
Pour prendre en charge les extraits différentiels, l’exemple de code a été modifié pour tirer parti /d2l/api/lp/(version)/dataExport/bds, qui a été introduit à la section 10.7.5. Cet itinéraire renvoie une liste de tous les extraits d’ensemble de données disponibles (complets et différentiels) et de toutes les métadonnées correspondantes, y compris DownloadLink, qui indique l’emplacement d’un ensemble de données donné.
Vue d’ensemble des modifications
Pour démontrer comment traiter les extraits complets et différentiels, l’exemple de code a été augmenté pour prendre en charge l’ensemble de données Inscriptions des utilisateurs. Les fichiers de schéma se trouvent dans le dossier de schéma.
Le plus grand changement apporté à l’exemple de code consiste à déterminer quel ensemble de données obtenir et comment le récupérer. Le code qui effectue un upsert (insertion ou mise à jour) dans la base de données est réutilisable et reste inchangé.
Données statiques
Nous avons ajouté l’extrait complet Inscriptions des utilisateurs à la liste complète des ensembles de données existante et une nouvelle liste pour stocker les extraits différentiels d’intérêt.
DataSetMetadata = collections.namedtuple('DataSetMetadata', ['plugin', 'table'])... FULL_DATA_SET_METADATA = [ ... DataSetMetadata( plugin = '533f84c8-b2ad-4688-94dc-c839952e9c4f', table = 'user_enrollments' )]DIFF_DATA_SET_METADATA = [ DataSetMetadata( plugin = 'a78735f2-7210-4a57-aac1-e0f6bd714349', table = 'user_enrollments' )]
Méthodes d’aide
Parce que nous allons faire des appels authentifiés à Brightspace plusieurs fois, la fonction d’aide suivante a été ajoutée :
def get_with_auth(endpoint, access_token) : headers = {'Authorization' : 'Bearer {}'.format(token_response['access_token'])} response = requests.get(endpoint, headers=headers) if response.status_code != 200 : logger.error('Status code : %s ; content : %s', response.status_code, response.text) response.raise_for_status() return response
Le code pour extraire le fichier zip et mettre à jour la base de données a été mis dans sa propre méthode d’aide pour la lisibilité :
def unzip_and_update_db(response_content, db_conn_params, table) : avec io. BytesIO(response_content) comme response_stream : avec zipfile. ZipFile(response_stream) as zipped_data_set : files = zipped_data_set.namelist() assert len(files) == 1 csv_name = files[0] with zipped_data_set.open(csv_name) as csv_data : update_db(db_conn_params, table, csv_data)
Téléchargement des ensembles de données
Tout d’abord, nous avons ajouté une option pour basculer entre le téléchargement d’extraits complets ou différentiels :
analyseur = argparse. ArgumentParser(description='Script pour le téléchargement d’ensembles de données.')parser.add_argument( '--differential', action='store_true', help='Use differential data sets instead of full data sets')args = parser.parse_args()
Nous avons ensuite ajouté une méthode pour obtenir un mappage de tous les ensembles de données et de leurs emplacements en utilisant l’itinéraire de l’ensemble de données de liste comme mentionné ci-dessus :
def get_plugin_link_mapping(config, access_token) : data_sets = [] next_page_url = '{bspace_url}/d2l/api/lp/{lp_version}/dataExport/bds'.format( bspace_url=config['bspace_url'], lp_version=API_VERSION ) alors que next_page_url ne l’est pas Aucun : list_response = get_with_auth(next_page_url, access_token) list_json = list_response.json() data_sets += list_json['BrightspaceDataSets'] next_page_url = list_json['NextPageUrl'] return { d['PluginId'] : d['DownloadLink'] pour d dans data_sets }... plugin_to_link = get_plugin_link_mapping(config, token_response['access_token'])
Sur la base de l’argument de ligne de commande, nous avons ajouté du code pour obtenir les liens de téléchargement pour tous les extraits complets ou différentiels qui nous intéressent :
# args.differential est vrai si '--differential' est fourni en tant que argumentdata_set_metadata = DIFF_DATA_SET_METADATA si args.differential else FULL_DATA_SET_METADATAplugin_to_link = get_plugin_link_mapping(config, token_response['access_token'])db_conn_params = { 'host' : config['dbhost'], 'dbname' : config['dbname'], 'user' : config['dbuser'], 'password' : config['dbpassword']}for plugin, table in data_set_metadata : response = get_with_auth( endpoint=plugin_to_link[plugin], access_token=token_response['access_token'] ) unzip_and_update_db(response.content, db_conn_params, table)
Le code de mise à jour de base de données inchangé fera correctement un upsert (insérer ou mettre à jour), quelle que soit la source de données (extrait complet ou différentiel).
Planification
Cet exemple de code n’inclut pas de fonctionnalité permettant de récupérer à partir d’un extrait différentiel manqué. Étant donné que les extraits différentiels ne contiennent que des données à partir de l’extrait différentiel précédent, un extrait différentiel manqué signifierait un écart de données dans la base de données cible, même si l’extrait différentiel suivant a été traité avec succès. Pour cette raison, cet exemple de code doit être planifié à la même cadence que le Différentiels des ensembles de données Brightspace tâche planifiée pour éviter de manquer un extrait différentiel.
La récupération à partir d’extraits différentiels manqués est actuellement hors de portée de l’exemple de code. Cependant, une atténuation simple serait de cibler la même base de données avec des extraits complets et différentiels, ce qui garantira que toutes les lacunes dans les données des extraits différentiels manqués seront comblées lors du traitement du prochain extrait quotidien. Alternativement, l’exemple de code pourrait être étendu pour examiner tous les extraits différentiels disponibles dans le PreviousDataSets à chaque exécution pour déterminer s’il a manqué des extraits.
Commentaires finaux
En tirant parti des itinéraires introduits dans la version 10.7.5, et avec quelques ajustements mineurs à notre exemple de code, nous avons démontré comment maintenir par programme une base de données à jour avec des extraits complets et différentiels. N’hésitez pas à poser des questions ou à laisser des commentaires ci-dessous !
Mise en forme du code par
http://markup.su/highlighter/
.