Как лучше всего включить одноразовый скрипт в ваше приложение Loopback 4? - PullRequest
0 голосов
/ 07 июня 2019

Я запутался, как запустить одноразовый скрипт как часть проекта Loopback 4, который заполняет значение для старых записей. Например. Я хочу включить поле createAt в запись пользователя и заполнить старые записи на основе отметки времени первого сообщения, сделанного каждым пользователем в системе.

Я попытался создать компонент, который будет запускаться только один раз, чтобы обновить все эти записи.

export class OneTimeComponent implements Component {
    constructor(
      @repository(UserRepository)
      public userRepository : UserRepository,
    ){
      this.start()
    }

    async start(){
      const users = await this.userRepository.find();

      users.forEach( user => {
        // find first post for user
        // get date 
        // update user.createdAt with date
      })
    }

}

export async function run(args: string[]) {
  const app = new BlogApiApplication();

  app.component(OneTimeComponent);

  await app.boot();

  // Connectors usually keep a pool of opened connections,
  // this keeps the process running even after all work is done.
  // We need to exit explicitly.
  process.exit(0);
}

run(process.argv).catch(err => {
  console.error('Cannot run this', err);
  process.exit(1);
});

Если я запускаю app.start(), сценарий будет пытаться запускаться при загрузке приложения, а затем я получаю сообщение о том, что этот адрес используется - очевидно, потому что запущено 2 приложения.

И я бы назвал этот файл скриптом пакета.

Для доступа к репозиториям это должен быть загрузочный скрипт? Или что-то еще?

Любая помощь высоко ценится.

1 Ответ

0 голосов
/ 17 июня 2019

Как запустить одноразовый скрипт как часть проекта Loopback 4, который заполняет значение для старых записей. Например. Я хочу включить поле createAt в запись пользователя и заполнить старые записи на основе отметки времени первого сообщения, сделанного каждым пользователем в системе.

Лично я бы внес эти изменения как часть миграции схемы базы данных, см. Миграции базы данных в документации LoopBack.

Большинство коннекторов LoopBack достаточно умны, чтобы добавить поле createdAt в таблицу User, если его еще нет. Заполнение значений остается для реализации.

Цитирование из Реализация дополнительных шагов миграции :

В некоторых сценариях приложению может потребоваться определить дополнительные ограничения схемы или заполнить базу данных предопределенными экземплярами модели. Это может быть достигнуто путем переопределения метода migrateSchema, предоставляемого mixin.

Пример ниже показывает, как это сделать в нашем примере приложения Todo.

/** FILE: src/application.ts **/
import {TodoRepository} from './repositories';
// skipped: other imports

export class TodoListApplication extends BootMixin(
  ServiceMixin(RepositoryMixin(RestApplication)),
) {
  // skipped: the constructor, etc.

  async migrateSchema(options?: SchemaMigrationOptions) {
    // 1. Run migration scripts provided by connectors
    await super.migrateSchema(options);

    // 2. Make further changes. When creating predefined model instances,
    // handle the case when these instances already exist.
    const todoRepo = await this.getRepository(TodoRepository);
    const found = await todoRepo.findOne({where: {title: 'welcome'}});
    if (found) {
      todoRepo.updateById(found.id, {isComplete: false});
    } else {
      await todoRepo.create({title: 'welcome', isComplete: false});
    }
  }
}

Я попытался создать компонент, который будет запускаться только один раз, чтобы обновить все эти записи. (...) Для доступа к репозиториям это должен быть загрузочный скрипт? Или что-то еще?

Если вы не хотите явно переносить схему и данные базы данных, запустив npm run migrate, вы можете изменить приложение для автоматического вызова autoMigrate как части экспортированной функции main.

Цитирование из Автообновление базы данных при запуске :

Чтобы автоматически обновлять схему базы данных при каждом запуске приложения, измените основной сценарий так, чтобы он выполнялся app.migrateSchema() после загрузки приложения (все репозитории были зарегистрированы), но до его фактического запуска.

/** FILE: src/index.ts **/

export async function main(options: ApplicationConfig = {}) {
  const app = new TodoListApplication(options);
  await app.boot();
  await app.migrateSchema();
  await app.start();

  const url = app.restServer.url;
  console.log(`Server is running at ${url}`);

  return app;
}

Последний вариант - использовать наблюдателей жизненного цикла (a.k.a «загрузочные скрипты» в LoopBack v3) - см. События жизненного цикла :

  1. Создайте новый наблюдатель, запустив lb4 observer (см. Генератор наблюдателя жизненного цикла ).

  2. Измените конструктор класса наблюдателя, чтобы внедрить репозитории моделей, с которыми вы хотите работать.

  3. Измените метод start, чтобы выполнить необходимые изменения в базе данных.

...