2021年12月

[解決]TypeORMでPostgreSQLのboolean型の列からデータを取得するとWindowsとLinuxで型が違う

本件解決いたしました。
結論から書くと、LinuxのPostgreSQLのis_two_factor_authentication_enabledがtext型、WindowsのPostgreSQLのis_two_factor_authentication_enabledがboolean型にしてしまっていました。

どうしてこうなったのかというと人為ミスです。
WindowsのPostgreSQLの定義をダンプして、Docker環境のPostgreSQLに流し込む…ということをしているのですが、Docker環境のPostgreSQLに一世代前のWindowsのPostgreSQLの定義を流し込んでおり、不一致が発生していました。



TypeORMでPostgreSQLのboolean型の列からデータを取得する場合、WindowsのPostgreSQLから取得した場合とLinuxのPostgreSQLで型が違いました。

擬似コードは以下のとおりです。
[Usersテーブルの定義抜粋]
@Entity()
export class Users {
  @Column({ type: "boolean", default: false })
  @Exclude()
  is_two_factor_authentication_enabled: boolean;
[確認コード抜粋]
let usersRepository: Repository;
usersRepository = getRepository(Users);

    const userDataFromDB = await usersRepository.findOne({
      where: {
        id: testUserId,
      },
    });
    console.log(typeof userDataFromDB.is_two_factor_authentication_enabled);
[出力]
接続先がWindowsで動かしているのPostgreSQLの場合
  ● Console

    console.log
      boolean
接続先がLinuxで動かしているのPostgreSQLの場合
  ● Console

    console.log
      string
なぜ違うのでしょうか…booleanで返ってきて欲しい…

cronを7日おきに実行したいのに1分おきに実行される

恥ずかしいので書きたくなかったのですが…、同じミスをして時間を食う方がいらっしゃるかもなので書きます。

cronを7日おきに実行したいのに1分おきに実行される事象が発生しました。
crontabの設定は以下のとおりです。
* * */7 * * /root/cron/test.sh
これは、2つ間違っています… 修正後の設定は以下のとおりです。
0 0 * * 0 /root/cron/test.sh

1つ目の間違いは、分と時の部分に*を設定してしまっているところです。
日のところに「*/7」と設定していますが、分のところに「*」と設定しているので、毎分実行されます。
日のところに「*/7」と設定して7日に1回だけ実行したい場合は、「0 0 */7」のように分と時も指定する必要があります。

2つ目の間違いは、日のところに「*/7」と設定すると…、「1-31/7」なので、1,8,15,22,29日に実行される…月を跨ぐときは、間隔が7日にならないということです。
29日に実行された後は、次の月の1日に実行されてしまいます。
1週間に1回実行したい場合は実行する曜日を適当に決めて、例えば「0 0 * * 0」のように曜日を指定する必要があります。

さくらインターネットの専用サーバ スタンダードシリーズのrsyslogdはreboot時に起動しない

ErogameScapeはさくらインターネットの専用サーバ スタンダードシリーズを借用しています。
CentOS8からAlmaLinuxへ移行した際に、借用してからはじめて再起動したのですが、rsyslog.serviceが起動していなかったため、ログが出力されていませんでした…
さくらの専用サーバ PHY コンパネの OS インストールで選択できる CentOS8も同様のようです。
systemctl start rsyslog.serviceで起動しました。
[root@sakura log]# systemctl status rsyslog.service
● rsyslog.service - System Logging Service
   Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; indirect; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:rsyslogd(8)
           https://www.rsyslog.com/doc/
[root@sakura log]# systemctl start rsyslog.service
[root@sakura log]# systemctl status rsyslog.service
● rsyslog.service - System Logging Service
   Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; indirect; vendor preset: enabled)
   Active: active (running) since Thu 2021-12-09 08:36:35 JST; 1s ago
reboot時にrsyslog.serviceがあがってくる設定を確認したところ
[root@sakura system]# systemctl is-enabled rsyslog
indirect
となっていました。
【systemctl】の使い方 〜オプション一覧,自動起動,list-units/list-unit-filesの見方, reloadとrestartの違い, runningとexitedの違い〜
によると、indirectは「static や indirect は有効/無効にするようなサービスではなく、他のサービスとの依存関係によって起動する類です。indirect は static と異なり、さらに別のunit ファイルを呼び出します。」とのことです。
【Linuxのサービス依存関係と順序関係】systemctl list-dependencies と systemd-analyze の見方
も読みまして、rsyslogdの依存関係を確認したところ…
[root@sakura system]# systemctl list-dependencies rsyslogd
rsyslogd.service
と、依存関係がないので…indirectですと起動しないのかな…と思いました。
[root@sakura system]# systemctl enable rsyslog
Created symlink /etc/systemd/system/multi-user.target.wants/rsyslog.service → /usr/lib/systemd/system/rsyslog.service.
[root@sakura system]# systemctl is-enabled rsyslog
enabled

として、reboot時にrsyslogが起動するようにいたしました。
なぜさくらインターネットの専用サーバはreboot時にrsyslogが起動しないようにしているのでしょうか…

NestJS + TypeORM + PostgreSQLにおけるTypeORMの設定のentitiesの設定について

NestJS + TypeORM + PostgreSQLにおけるTypeORMの設定のentitiesの設定について、サーバーを起動する場合と、npm run testでテストする場合とで、設定をかえないといけないです。
※ぐぐると、entitiesの設定についてはまっている方が多いけど、いまいちしゃきっとした回答が見つかりませんでした。自分もいろいろ試行錯誤した結果、下に書いた内容に行き着いたのですが、どうしてそうなるのかをちゃんと説明できない(調べられない)です。分かる方にご教示頂きたいです…

[困ったこと]
NestJS + TypeORM + PostgreSQLの構成でサーバーは問題なく起動し、リクエストに対してレスポンスを返すのですが、npm run test(Jestによるテスト)をすると以下のエラーが発生しテストが失敗する。
    RepositoryNotFoundError: No repository for "Users" was found. Looks like this entity is not registered in current "default" connection?

[TypeORMの設定]
app.module.tsで
@Module({
  imports: [
    TypeOrmModule.forRoot(),
    TypeOrmModule.forFeature([Users]),
  ],
とし、ルートディレクトリにormconfig.jsonを配置した。
ormconfig.jsonの内容は以下のとおり。
{
  "name": "default",
  "type": "postgres",
  "host": "localhost",
  "port": 5432,
  "username": "postgres",
  "password": "postgres",
  "database": "pong",
  "entities": ["dist/entities/**/*.entity.js"],
  "migrations": ["dist/migrations/**/*.js"],
  "logging": false,
  "synchronize": false
}

[解決方法]
npm run test(Jestによるテスト)の場合は、entitiesを以下のように設定する。
["./src/entities/**/*.entity.ts"]
具体的には、spec.tsファイルを以下のように書いた。
describe("AppController", () => {
  let appController: AppController;
  let app: TestingModule;

  beforeAll(async () => {
    app = await Test.createTestingModule({
      imports: [
        TypeOrmModule.forRoot(),
        TypeOrmModule.forRootAsync({
          useFactory: async () =>
            Object.assign(await getConnectionOptions(), {
              entities: getEntites(),
            }),
        }),
        TypeOrmModule.forFeature([Users]),
      ],
(中略)
    }).compile();

    appController = app.get(AppController);
  });

  afterAll(() => app.close());

getEntites()の内容は以下のとおり。
export function getEntites() {
  return ["./src/entities/**/*.entity.ts"];
}

[考えたこと]
  "entities": ["dist/entities/**/*.entity.js"],
と設定して、Jestでテストをしようとすると
RepositoryNotFoundError: No repository for "Users" was found. Looks like this entity is not registered in current "default" connection?
となる。
  "entities": ["./src/entities/**/*.entity.ts"],
と設定して、npm run start:devすると
[Nest] 17012  - 2021/12/08 16:53:42   ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1)...
D:\42\ft_transcendence\github\pong\server\src\entities\accomplishes.entity.ts:1
import {
^^^^^^

SyntaxError: Cannot use import statement outside a module
となる。 以上から、NestJSはコンパイルされたJavaScriptで動作するので、TypeORMに読み込ませるEntityの情報はJavaScript(.js)でなければならない(importがSyntaxErrorになる)のに対して、Jestでテストをする場合、テストファイルはTypeScriptで書かれているものをJestがトランスコンパイルして生成されたJavascriptで動作するので、TypeORMに読み込ませるEntityの情報は(おそらく依存関係の解決のために)TypeScript(.ts)でなければならない(dist/entities/*/.entity.jsを読み込んでくれない?)のだと思います、たぶん… ちゃんとした理由をご存知でしたらご教示頂きたいです。

[試験環境]
https://github.com/hiroin/typeorm-setting-entities

Cookieをセットしてfile()でWebページを取得する

ErogameScapeのキャンペーン情報は、FANZAやDLsiteのキャンペーンの情報の画面のHTMLを取得し、ErogameScapeで持っている情報と突き合わせて、生成しています。
HTMLの取得は
$data = file("https://dlsoft.dmm.co.jp/list/article=keyword/id=300080/sort=ranking/");
のようにしていました。
しかし、2021/12/01時点で、この方法で取得しようとすると、「あなたは18歳以上ですか?」の画面に飛ばされるようになりました。

「あなたは18歳以上ですか?」で「はい」を選択すると、レスポンスヘッダーに
set-cookie: age_check_done=1; expires=Fri, 31-Dec-2021 06:48:55 GMT; path=/; domain=dmm.co.jp; httponly
が含まれるレスポンスがかえってきて、再度、https://dlsoft.dmm.co.jp/list/article=keyword/id=300080/sort=ranking/にアクセスする、という流れになります。

以上から、file()を呼ぶときに、「Cookie: age_check_done=1」を追加する必要がでてきました。
$options =array(
    'http' =>array(
    'method' => "GET",
    'header' => "Cookie: age_check_done=1\r\n",
    )
);
$data = file("https://dlsoft.dmm.co.jp/list/article=keyword/id=300080/sort=ranking/", 0, $options);
とすることで、https://dlsoft.dmm.co.jp/list/article=keyword/id=300080/sort=ranking/の内容を取得することができました。

[参考]



記事検索